Предложение COLLATE нельзя использовать в выражениях, содержащих предложение COLLATE.

У меня есть две таблицы: tab1 и tab2. Каждая таблица имеет только один столбец VARCHAR(MAX).

Мне нужно получить только те пары значений, которые равны, но различаются только регистром.

Пример ввода:

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. удалить все дубликаты, используя сортировку с учетом регистра на вкладке 2
  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 (я пробовал их - они почти не замедляют выполнение).


person John Wales    schedule 07.11.2012    source источник


Ответы (1)


Поскольку 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
person RichardTheKiwi    schedule 07.11.2012