3

tab1 と tab2 の 2 つのテーブルがあります。すべてのテーブルには、VARCHAR(MAX) 列が 1 つだけあります。

等しい値のペアのみを取得する必要がありますが、大文字と小文字のみが異なります。

入力例:

tab1.t1     tab2.t2
-----------------------
fff     fff
FFF     fff
Fff     fff
FFF     FFA
FfA     FFF
FFF     aaa
bbb     aaa

Related output:

t1      t2
-----------------------
fff     FFF
FFF     fff
Fff     fff
Fff     FFF
FfA     FFA

テーブル tab1 と tab2 は、実際のデータベースでは十分な大きさです (~ 800-1000 行)。そして、この操作を行う必要がある列は約 500 ~ 600 あります。

だから私は速い解決策を書く必要があります。私はアルゴリズムを書きます:

  1. タブ1から大文字と小文字を区別する照合を使用してすべての重複を削除します
  2. tab2 から大文字と小文字を区別する照合を使用してすべての重複を削除します
  3. 大文字と小文字を区別しない照合を使用して、前の手順の結果セットを結合します
  4. 大文字と小文字を区別する照合を使用して、値が等しくない行を除外 (WHERE 句)
  5. 大文字と小文字を区別する照合を使用して重複行を削除する

私はそうしようとしました:

SELECT DISTINCT tt.t1 COLLATE Cyrillic_General_CS_AS, tt.t2 COLLATE Cyrillic_General_CS_AS
FROM (
    SELECT tt1.t1, tt2.t2
    FROM 
    (
        SELECT tab1.t1 COLLATE Cyrillic_General_CS_AS
                       AS t1
        FROM (VALUES('fff'),('FFF'),('Fff'),('FFF'),('FfA'),('FFF'),('bbb')) AS tab1(t1)
        GROUP BY tab1.t1 COLLATE Cyrillic_General_CS_AS
    ) tt1 INNER JOIN
    (
        SELECT tab2.t2 COLLATE Cyrillic_General_CS_AS
                       AS t2
        FROM (VALUES('fff'),('fff'),('fff'),('FFA'),('FFF'),('aaa'),('aaa')) AS tab2(t2)
        GROUP BY tab2.t2 COLLATE Cyrillic_General_CS_AS
    ) tt2
    ON tt1.t1 = tt2.t2 COLLATE Cyrillic_General_CI_AS
) AS tt
WHERE tt.t1 <> tt.t2 COLLATE Cyrillic_General_CS_AS

しかし、エラーが発生します:

「COLLATE句を含む式ではCOLLATE句を使用できません。」

ユーザー定義関数、一時テーブルを使用したり、group by 句を削除したりせずに、この問題を回避する方法を教えてください (私はそれらを試しましたが、実行がほとんど遅くなりません)。

4

1 に答える 1

2

SQL Server は任意の順序で JOIN を処理できるため、

  1. 最終出力で評価される繰り越し式
  2. データからの最初の検索を合理化するのと同じくらい早い段階で式を解決する

COLLATE の適用を強制する段階を保証することはできません。そのため、任意の列/式に一度しか適用できません。外側のクエリには既に DISTINCT があるため、派生テーブルでは GROUP BY は不要です。中間結果セットが削減されると思われる場合でも。


SELECT DISTINCT tt.t1 COLLATE Cyrillic_General_CS_AS, tt.t2 COLLATE Cyrillic_General_CS_AS
FROM (
    SELECT tt1.t1, tt2.t2
    FROM 
        (VALUES('fff'),('FFF'),('Fff'),('FFF'),('FfA'),('FFF'),('bbb')) tt1(t1)
    INNER JOIN
        (VALUES('fff'),('fff'),('fff'),('FFA'),('FFF'),('aaa'),('aaa')) tt2(t2)
    ON tt1.t1 = tt2.t2
) AS tt
WHERE tt.t1 <> tt.t2 COLLATE Cyrillic_General_CS_AS
于 2012-11-07T18:37:28.473 に答える