Equals(=)とLIKE


280

SQLを使用=する場合、WHERE句の代わりに使用する利点はありLIKEますか?

特別なオペレータがなければ、LIKE=同じですよね?


4
dbタイプを指定する必要があるかもしれません... mssql、mysql、oracle?
アレンライス

1
あなたの質問は、少なくともlike-operatorタグに5投票しています。sql-like同義語として提案するようにお願いできますか?
Kermit 2013

@FreshPrinceOfSO、私は十分な評判を得たときにそれを行います。ありがとう。
Travis

回答:


270

異なるオペレーター

LIKE=は別の演算子です。ここでのほとんどの回答はワイルドカードのサポートに焦点を当てていますが、これらの演算子の違いはこれだけではありません!

=数値と文字列を操作する比較演算子です。文字列を比較する場合、比較演算子は文字列全体を比較します

LIKE比較文字列演算子で文字ずつ

問題を複雑にするために、両方の演算子は比較の結果を重要な影響を及ぼす可能性がある照合を使用します

動機付けの例

最初に、これらの演算子が明らかに異なる結果を生成する例を特定しましょう。MySQLのマニュアルから引用させてください:

SQL標準に従って、LIKEは文字ごとにマッチングを実行するため、=比較演算子とは異なる結果を生成する可能性があります。

mysql> SELECT 'ä' LIKE 'ae' COLLATE latin1_german2_ci;
+-----------------------------------------+
| 'ä' LIKE 'ae' COLLATE latin1_german2_ci |
+-----------------------------------------+
|                                       0 |
+-----------------------------------------+
mysql> SELECT 'ä' = 'ae' COLLATE latin1_german2_ci;
+--------------------------------------+
| 'ä' = 'ae' COLLATE latin1_german2_ci |
+--------------------------------------+
|                                    1 |
+--------------------------------------+

MySQLのマニュアルのこのページが呼び出されることに注意してください文字列比較関数を、そして=それが暗示され、議論されていない=厳密に文字列比較関数ではありません。

どのように機能します=か?

SQL標準§8.2はどのように説明し=た文字列を比較します。

2つの文字列の比較は、次のように決定されます。

a)Xの文字の長さがYの文字の長さと等しくない場合、比較のために、短い文字列は長い文字列の長さに拡張されたそれ自体のコピーで効果的に置き換えられます。 1つ以上のパッド文字の右側にある連結によって、パッド文字はCSに基づいて選択されます。CSにNO PAD属性がある場合、パッド文字は、XとYの文字セット内のどの文字とも異なる実装依存の文字であり、CSの下のどのストリングよりも照合が少なくなります。それ以外の場合、埋め込み文字はです。

b)XとYの比較結果は、照合シーケンスCSによって与えられます。

c)照合シーケンスに応じて、2つの文字列は、長さが異なる場合や、文字のシーケンスが異なる場合でも、等しいと比較される場合があります。操作MAX、MIN、DISTINCT、グループ化列への参照、およびUNION、EXCEPT、およびINTERSECT演算子が文字列を参照する場合、これらの操作によって選択される特定の値は、そのような等しい値のセットから実装依存です。

(強調が追加されました。)

これは何を意味するのでしょうか?つまり、文字列を比較する場合、=演算子は現在の照合順序の薄いラッパーにすぎません。照合は、文字列を比較するためのさまざまなルールを持つライブラリです。MySQLからのバイナリ照合の例を次に示します

static int my_strnncoll_binary(const CHARSET_INFO *cs __attribute__((unused)),
                               const uchar *s, size_t slen,
                               const uchar *t, size_t tlen,
                               my_bool t_is_prefix)
{
  size_t len= MY_MIN(slen,tlen);
  int cmp= memcmp(s,t,len);
  return cmp ? cmp : (int)((t_is_prefix ? len : slen) - tlen);
}

この特定の照合は、バイト単位で比較されます(これが「バイナリ」と呼ばれる理由です。文字列に特別な意味はありません)。他の照合では、より高度な比較が提供される場合があります。

たとえば、大文字と小文字を区別しない比較をサポートするUTF-8照合は次のとおりです。コードが長すぎてここに貼り付けることはできませんが、そのリンクに移動しての本文を読んでくださいmy_strnncollsp_utf8mb4()。この照合は一度に複数のバイトを処理でき、さまざまな変換(大文字と小文字を区別しない比較など)を適用できます。=オペレータは完全照合の気まぐれから抽象化されます。

どのように機能しますLIKEか?

SQL標準§8.5はどのように説明しLIKEた文字列を比較します。

<述語>

M LIKE P

Mが次のような部分文字列に分割されている場合はtrueです。

i)Mのサブストリングは、Mの0個以上の連続する<文字表現>のシーケンスであり、Mの各<文字表現>は、正確に1つのサブストリングの一部です。

ii)Pのi番目の部分文字列指定子が任意の文字指定子である場合、Mのi番目の部分文字列は任意の単一の<文字表現>です。

iii)Pのi番目の部分文字列指定子が任意の文字列指定子である場合、Mのi番目の部分文字列は0個以上の<文字表現>のシーケンスです。

iv)Pのi番目の部分文字列指定子が任意の文字指定子でも任意の文字列指定子でもない場合、Mのi番目の部分文字列は、<like predicate>の照合シーケンスに従って、その部分文字列指定子と等しくなります。 Mへの<space>文字の追加。その部分文字列指定子と同じ長さ。

v)Mの部分文字列の数は、Pの部分文字列指定子の数と同じです。

(強調が追加されました。)

これはかなり冗長なので、分解してみましょう。項目iiとiiiは、それぞれワイルドカード_とを参照してい%ます。Pワイルドカードが含まれていない場合、アイテムivのみが適用されます。これは、OPによって提起された関心のあるケースです。

この場合、現在の照合を使用MPて、各 "部分文字列"(個々の文字)を各部分文字列と比較します。

結論

一番下の行は、=文字列をLIKE比較するときに、一度に1 文字を比較しながら文字列全体を比較することです。どちらの比較でも現在の照合が使用されます。この違いは、この投稿の最初の例で証明されているように、場合によっては異なる結果になります。

あなたはどちらを使うべきですか?誰もそれを伝えることはできません—あなたのユースケースに合ったものを使う必要があります。比較演算子を切り替えることによって時期尚早に最適化しないでください。


4
"EQUALSは2つのデータをバイトごとに比較します":単純化され、あまり頻繁には当てはまりません。これは、EQUALS(=)の動作がCOLLATEで変更され、文字の代わりに文字クラスが比較されるためです。たとえば、dev.mysql.com / doc / refman / 5.0 / en / charset -collat​​e.html(MySQL)またはsqlmag.com/blog/forcing-collat​​ion-where-clause-22-jun-2011(SQL Server)を参照してください。
Peter B 14

11
これが正解です。私たちは何をするかを知ってLIKEいますが、この答えは、withing またはpresent を使用するLIKEことはを使用することとまったく同じないことを驚くほど説明しています。あなたの答えが千の賛成票を受け取るかもしれません。%_=
rinogo 14

1
@mehaseこれは真実ではありません。私のvarchar型のフィールドに値が含まれている場合は'AbCdEfG'、と私はWHERE MyCol = 'abcdefg'、私はまだ彼らは明確ではないバイトごと同等であっても、その行を取り戻す
キップ

1
PeterBと@Kipはどちらも良い点を挙げています。照合がこれらの演算子にどのように影響するかを説明するために、回答を改善しました。
Mark E. Haase、2015年

2
これはもう真実ではないようです:set charset latin1; SELECT 'ä' = 'ae' COLLATE latin1_german2_ci;0をSELECT 'ä' LIKE 'ae' COLLATE latin1_german2_ci;与え、0も与えます。
joanq 2016年

170

等号(=)演算子は、「比較演算子が2つの値を比較して等しいかどうか」です。つまり、SQLステートメントでは、方程式の両辺が等しくない限り、trueを返しません。例えば:

SELECT * FROM Store WHERE Quantity = 200;

LIKE演算子は、「文字列値をワイルドカード文字を含むパターン文字列と照合する」「パターン照合比較を実装する」。例えば:

SELECT * FROM Employees WHERE Name LIKE 'Chris%';

LIKEは通常、文字列でのみ使用され、(等しいと思う)はより高速です。等号演算子は、ワイルドカード文字をリテラル文字として扱います。返される結果の違いは次のとおりです。

SELECT * FROM Employees WHERE Name = 'Chris';

そして

SELECT * FROM Employees WHERE Name LIKE 'Chris';

同じ結果が返されますが、LIKEを使用すると、通常、パターンマッチと同様に時間がかかります。しかしながら、

SELECT * FROM Employees WHERE Name = 'Chris%';

そして

SELECT * FROM Employees WHERE Name LIKE 'Chris%';

"="を使用すると、 "Chris%"が返される結果のみが返され、LIKE演算子は "Chris"で始まるすべての結果を返します。

お役に立てば幸いです。いくつかの良い情報がここにあります


108
OPはLIKEを使用する場合と=を使用する場合を知っているという印象を受けています。彼は、ワイルドカードが存在しないときにパフォーマンスの違いがあるかどうか疑問に思っています。この回答ではこれについて簡単に触れていますが、この回答の95%はあまり関係がないと思います。
アウトロープログラマ、

1
とても本当です。質問に答えたとき、質問が同じだったかどうかはわかりません。そうだとすれば、演奏について聞かれた部分を逃した。ご覧いただきありがとうございます。
achinda99

9
この答えはひどいです。LIKEと '='は完全に異なる演算子ですが、一部の小さなサブセットではたまたま同様に動作します。後世のために、ここにある残りの返信を読むか、少なくともこれをメモリにコミットする前に「mysql like」についてgoogleにしてください。
マークE.ハース

3
一方、この答えは私がググった質問に答えました。回答が質問のタイトルに答えれば、コンテンツと同じくらい良い場合があります。
CorayThan 2014

覚えておくと良いのは、charとvarchar2を使用するときです。charとcharを比較した場合。データベースを比較する前に、まず最初の「変数」の長さを2番目の「変数」の長さに変換します。charとvarchar2を比較すると、データベースは何もしません。 docs.oracle.com/cd/A64702_01/doc/server.805/a58236/c_char.htm
xild

18

これは、SQLの「like」と「=」のパフォーマンスの質問に対する私の別の回答のコピー/貼り付けです。

mysql 5.5を使用した個人的な例:300万行の1つと1万行の1つの2つのテーブル間に内部結合がありました。

以下のように(ワイルドカードなしで)インデックスにいいね!を使用すると、約30秒かかりました:

where login like '12345678'

私が得る「説明」を使用して:

ここに画像の説明を入力してください

同じクエリで「=」を使用すると、約0.1秒かかりました。

where login ='12345678'

私が得る「説明」を使用して:

ここに画像の説明を入力してください

ご覧のlikeように、インデックスシークは完全にキャンセルされたため、クエリに300倍の時間がかかりました。


17

LIKE=は異なります。LIKE検索クエリで使用するものです。_(単純な文字のワイルドカード)や%(複数文字のワイルドカード)などのワイルドカードも使用できます。

= 完全一致が必要な場合に使用してください。

このサイトは説明します LIKE


11

LIKEでワイルドカードを使用する可能性を除いて、1つの違いは末尾のスペースにあります。=演算子は末尾のスペースを無視しますが、LIKEは無視しません。


4
これはMySQLとMS SQLには当てはまりますが、PostgreSQLには当てはまりません。
ブルーノ

10

データベースシステムに依存します。

一般に、特殊文字がない場合、はい、=、LIKEは同じです。

ただし、一部のデータベースシステムでは、照合演算子の設定が演算子によって異なる方法で処理される場合があります。

たとえば、MySQLでは、文字列の=との比較では、デフォルトで常に大文字と小文字が区別されないため、特殊文字のないLIKEも同じです。他の一部のRDBMSでは、LIKEは大文字と小文字を区別しませんが、=はそうではありません。


この奇妙さの概要のようなものはありますか?
ガンボ

9

この例では、varcharcolに''この列に対する空のセルが含まれておらず、セルがないことは当然のことと考えています

select * from some_table where varcharCol = ''
select * from some_table where varcharCol like ''

最初のものは0行の出力になり、2番目のものはリスト全体を表示します。=は厳密に一致するケースですが、likeはフィルターのように機能します。フィルターに基準がない場合、すべてのデータが有効です。

のような-その目的のために少し遅く動作し、varcharおよび同様のデータでの使用を目的としています。


6

完全一致を検索する場合は、=とLIKEの両方を使用できます。

この場合、「=」を使用すると少し高速になります(完全一致の検索)。SQLServer Management Studioで同じクエリを2回使用して、「=」を1回、「LIKE」を1回使用して、これを自分で確認できます。次に、「クエリ」/「実際の実行プランを含める」を使用します。

2つのクエリを実行すると、結果が2回表示され、さらに2つの実際の実行プランが表示されます。私の場合、それらは50%対50%に分割されましたが、「=」実行プランの方が「推定サブツリーコスト」が小さくなっています(左端の「SELECT」ボックスにカーソルを合わせると表示されます)。大きな違いではありません。

ただし、LIKE式でワイルドカードを使用して検索を開始すると、検索パフォーマンスが低下します。"LIKE Mill%"を検索すると、かなり高速になる可能性があります。SQLServerは、その列にインデックスがあれば、それを使用できます。"LIKE%expression%"の検索は、SQL Serverがこの検索を満たす唯一の方法が全テーブルスキャンを実行することであるため、恐ろしく遅くなります。したがって、LIKEには注意してください。

マーク


-1は「いいえ」です。常に少し速いとは限りません。%mystring%を使用して列にインデックスを付けると、数桁遅くなります。実際、その価値のあるコード標準には、ミッキーマウスデータベースよりも大きなデータベースで同様に使用するべきでない場合とそうでない場合についての厳しいガイドラインがあります。
Cruachan、

1
すべてのケースで少し遅くなるとは決して言いませんでした。完全一致を検索すると、少し遅くなると言いました。特に、LIKEを使用してワイルドカードを使用する検索は、特に検索項目の最初と最後で非常に遅くなります。
marc_s 2009

そして、はい、同意します。LIKEを使用するかどうかについては、明確なガイドラインが必要です(ワイルドカードで検索する必要がある場合のみ)。しかし、再び-理論的には、理論と実践の間に違いはありませんが、実際には.......
marc_s

6

=を使用すると、実行時にクエリを作成するときに、ワイルドカードや特殊文字の文字列の競合を回避できます。

これにより、LIKE句に含まれる可能性のあるすべての特殊なワイルドカード文字をエスケープする必要がなくなり、意図した結果が得られないため、プログラマーの生活が楽になります。結局のところ、=は99%のユースケースシナリオであり、毎回それらをエスケープしなければならないのは面倒です。

90年代に目を転がす

また、少し遅いのではないかと思いますが、パターンにワイルドカードがない場合は重要ではないでしょう。


6

パフォーマンスに関する元の質問に対処するには、インデックスの使用率が重要です。単純なテーブルスキャンが発生した場合、「LIKE」と「=」は同一です。インデックスが含まれる場合、LIKE句の形成方法によって異なります。具体的には、ワイルドカードの場所はどこですか?


以下を検討してください。

CREATE TABLE test(
    txt_col  varchar(10) NOT NULL
)
go

insert test (txt_col)
select CONVERT(varchar(10), row_number() over (order by (select 1))) r
  from master..spt_values a, master..spt_values b
go

CREATE INDEX IX_test_data 
    ON test (txt_col);
go 

--Turn on Show Execution Plan
set statistics io on

--A LIKE Clause with a wildcard at the beginning
DBCC DROPCLEANBUFFERS
SELECT txt_Col from test where txt_col like '%10000'
--Results in
--Table 'test'. Scan count 3, logical reads 15404, physical reads 2, read-ahead reads 15416, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
--Index SCAN is 85% of Query Cost

--A LIKE Clause with a wildcard in the middle
DBCC DROPCLEANBUFFERS
SELECT txt_Col from test where txt_col like '1%99'
--Results in
--Table 'test'. Scan count 1, logical reads 3023, physical reads 3, read-ahead reads 3018, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
--Index Seek is 100% of Query Cost for test data, but it may result in a Table Scan depending on table size/structure

--A LIKE Clause with no wildcards
DBCC DROPCLEANBUFFERS
SELECT txt_Col from test where txt_col like '10000'
--Results in
--Table 'test'. Scan count 1, logical reads 3, physical reads 2, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
--Index Seek is 100% of Query Cost
GO

--an "=" clause = does Index Seek same as above
DBCC DROPCLEANBUFFERS
SELECT txt_Col from test where txt_col = '10000'
--Results in
--Table 'test'. Scan count 1, logical reads 3, physical reads 2, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
--Index Seek is 100% of Query Cost
GO


DROP TABLE test

また、「=」と「LIKE」を使用する場合、クエリプランの作成にごくわずかな違いがある場合があります。


4

ワイルドカードの他に、=AND の違いはLIKE、SQLサーバーの種類と列の型の両方に依存します。

この例を見てみましょう:

CREATE TABLE testtable (
  varchar_name VARCHAR(10),
  char_name CHAR(10),
  val INTEGER
);

INSERT INTO testtable(varchar_name, char_name, val)
    VALUES ('A', 'A', 10), ('B', 'B', 20);

SELECT 'VarChar Eq Without Space', val FROM testtable WHERE varchar_name='A'
UNION ALL
SELECT 'VarChar Eq With Space', val FROM testtable WHERE varchar_name='A '
UNION ALL
SELECT 'VarChar Like Without Space', val FROM testtable WHERE varchar_name LIKE 'A'
UNION ALL
SELECT 'VarChar Like Space', val FROM testtable WHERE varchar_name LIKE 'A '
UNION ALL
SELECT 'Char Eq Without Space', val FROM testtable WHERE char_name='A'
UNION ALL
SELECT 'Char Eq With Space', val FROM testtable WHERE char_name='A '
UNION ALL
SELECT 'Char Like Without Space', val FROM testtable WHERE char_name LIKE 'A'
UNION ALL
SELECT 'Char Like With Space', val FROM testtable WHERE char_name LIKE 'A '
  • MS SQL Server 2012を使用すると、LIKE列タイプがの場合を除いて、末尾のスペースは比較で無視されますVARCHAR

  • MySQL 5.5を使用すると、との両方で、末尾のスペースは無視されますが、無視され=ません。LIKECHARVARCHAR

  • 使用するPostgreSQLの9.1、スペースは両方で重要である=LIKE使用してVARCHAR、ではなくてCHAR(参照マニュアルを参照して)。

    の動作LIKEもによって異なりCHARます。

    上記と同じデータを使用CASTし、列名に明示を使用すると、違いが生じます。

    SELECT 'CAST none', val FROM testtable WHERE char_name LIKE 'A'
    UNION ALL
    SELECT 'CAST both', val FROM testtable WHERE
        CAST(char_name AS CHAR) LIKE CAST('A' AS CHAR)
    UNION ALL
    SELECT 'CAST col', val FROM testtable WHERE CAST(char_name AS CHAR) LIKE 'A'
    UNION ALL
    SELECT 'CAST value', val FROM testtable WHERE char_name LIKE CAST('A' AS CHAR)

    これは、「CAST both」と「CAST col」の行のみを返します。


2

LIKEキーワードには、間違いなく「パフォーマンス値札」が付属しています。つまり、クエリで使用されるワイルドカード文字を含む可能性のある入力フィールドがある場合、入力にワイルドカードの1つが含まれている場合のみ LIKEを使用することをお勧めします。それ以外の場合は、標準の等価比較を使用します。

宜しくお願いします...


1

本当にそれはあなたがクエリに何をさせたいかということにかかっています。完全一致を意味する場合は、=を使用します。あいまいな一致を意味する場合は、LIKEを使用します。あなたが何を意味するかを言うことは、通常、コードでの良い方針です。


1

Oracleでは、ワイルドカードのない「like」は「equals」と同じ結果を返しますが、追加の処理が必要になる場合があります。Tom Kyte氏によれば、Oracleは、ワイルドカードのない「like」をリテラルの使用時に「等しい」として扱いますが、バインド変数の使用時は扱いません。


0

=そしてLIKE同じではありません。

  1. = 完全に一致する文字列
  2. LIKE ワイルドカード(%)を含む可能性のある文字列に一致します

2
不十分な回答

ワイルドカードなしで使用することもできます。同じケースの違いについて質問されました。
M-Razavi
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.