大文字と小文字を区別するデータベースで大文字と小文字を区別しないLIKEを行う方法


11

私のベンダーでは、データウェアハウスデータベースで大文字と小文字を区別する必要がありますが、それに対して大文字と小文字を区別しないクエリを実行する必要があります。

大文字と小文字を区別するデータベースで、大文字と小文字を区別しないようにこれをどのように記述しますか?

    Where Name like '%hospitalist%'

回答:


17

選択クエリに新しい照合を追加して、大文字と小文字を区別するか区別しないかを見つけることができます。

-- Case sensitive example
SELECT *
FROM TABLE 
WHERE Name collate SQL_Latin1_General_CP1_CS_AS like '%hospitalist%'

-- Case insensitive example
SELECT *
FROM TABLE 
WHERE Name collate SQL_Latin1_General_CP1_CI_AS like '%hospitalist%'

これが示す可能性のあるパフォーマンスの問題に注意してください。照合を実行するときに、値を調整/検索するためにクラスター化インデックスをスキャンする必要があります。LIKE作品の記述方法によっても、クエリは引数を使用できなくなります。

私はケンドラリトルの SELECTセミナークラスから照合トリックを取得しました。MS SQL TipsのBen Snaideroから追加の照合情報を見つけることができます

Collat​​eのMSDN。


@stom 2つの方法があります。a)パフォーマンスの問題を時間ではなく処理時間に移動しますselect。これは、変換されたデータのサブセットを使用して新しい列を作成し、通常はETLを実行するときにその列にインデックスを付けることで実行できます。これは維持費がかかり、優れた方法ではありません。B)クエリ検索を引数付きまたは検索可能にすることができます。するクエリを変更するSELECT * FROM TABLE WHERE VALUE LIKE %hospitalistか、SELECT * FROM TABLE WHERE VALUE LIKE hospitalist%働くだろう。それとは別に、不良なデザインの速度を上げるためのハードウェアや機能を調べています。
Shaulinator

14

あなたが間にできるようなスカラー関数を使用UPPERまたはLOWERを、あなたがすることができますので、それはもはや大文字と小文字が区別だと列を再照合、これらは、すべてのデータ変換を求めるインデックスを可能にすることはありませんベースのデータに対して行うことが必要と近づきます。また、ワイルドカードを使用してLIKEをリードしているので、これはとにかく、このシナリオでは、あなたの懸念の限りではありませんが、あなたは効率的な方法で、文字列の左側の部分を検索したい場合は、ANDオプティマイザを可能にインデックスを検索するには、次のように角かっこ([])を使用して文字列を指定できます。

SELECT *
FROM TABLE 
WHERE Name LIKE '[hH][oO][sS][pP][iI][tT][aA][lL][iI][sS][tT]%'

この例(ここのdbfiddleリンク)は、私が何を意味しているのかを示すのに優れています。

CREATE TABLE #tmp_cohellation_fun
(
        ID  INT IDENTITY(1,1) PRIMARY KEY CLUSTERED
    ,   myValue VARCHAR(50) COLLATE SQL_Latin1_General_CP1_CS_AS
)

-- Garbage values to represent data you don't want
INSERT INTO #tmp_cohellation_fun
SELECT  CAST(NEWID() AS VARCHAR(50))
FROM master.sys.configurations t1
    CROSS JOIN master.sys.configurations t2
    CROSS JOIN master.sys.configurations t3;

-- Sprinkle a little bit of good data
INSERT INTO #tmp_cohellation_fun
        (myValue)
VALUES  ('Apple')
    ,   ('apple')

-- Another healthy helping of garbage that we don't care about
INSERT INTO #tmp_cohellation_fun
SELECT  CAST(NEWID() AS VARCHAR(50))
FROM master.sys.configurations t1
    CROSS JOIN master.sys.configurations t2
    CROSS JOIN master.sys.configurations t3;

-- Some more good data
INSERT INTO #tmp_cohellation_fun
        (myValue)
VALUES
        ('aPple')
    ,   ('APPLE')
    ,   ('APple')


-- Final insert of garbage that we don't care about
INSERT INTO #tmp_cohellation_fun
SELECT  CAST(NEWID() AS VARCHAR(50))
FROM master.sys.configurations t1
    CROSS JOIN master.sys.configurations t2
    CROSS JOIN master.sys.configurations t3
;

-- Create a nonclustered rowstore index
CREATE INDEX ix_myValue ON #tmp_cohellation_fun (myValue)
;

SET STATISTICS XML ON
;

-- Seek, but incorrect results
SELECT  *
FROM    #tmp_cohellation_fun
WHERE   myValue LIKE 'apple%'
;

-- Scan, with correct results
SELECT  *
FROM    #tmp_cohellation_fun
WHERE   myValue COLLATE SQL_Latin1_General_CP1_CI_AS LIKE 'apple%'
;

-- Seek, with correct results
SELECT  *
FROM    #tmp_cohellation_fun
WHERE   myValue LIKE '[aA][pP][pP][lL][eE]%'
;

SET STATISTICS XML OFF
;

DROP TABLE IF EXISTS #tmp_cohellation_fun

大好きです。大文字と小文字を区別する照合から大文字と小文字を区別しない照合を2つの他の同一の照合がある場合、SQLがこのように適切にフォールバックできなかったのは私を超えています。逆に行けない理由がわかります。とにかくこれは良いものです。
John Leidegren、

13

クエリを非SARGableCOLLATEにするため、これと回答の両方がパフォーマンスに影響しますが、これを行う最も簡単な方法は(Edgarがコメントで示唆しているように)です。

WHERE LOWER(Name) LIKE '%hospitalist%' 

または

WHERE UPPER(Name) LIKE '%HOSPITALIST%' 
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.