COLLATE子句不能用于包含COLLATE子句的表达式

时间:2012-11-07 16:35:41

标签: sql-server tsql database-performance

我有两个表: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列的操作。

所以我需要写一个快速的解决方案。 我写了一个alghoritm:

  1. 使用tab1
  2. 中的区分大小写的排序规则删除所有重复项
  3. 使用tab2
  4. 中的区分大小写的排序规则删除所有重复项
  5. 使用不区分大小写的排序规则来连接先前步骤中的结果集
  6. 使用区分大小写的排序规则过滤掉(WHERE子句)哪些值不等于
  7. 使用区分大小写的排序规则删除重复的行
  8. 我试过了:

    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子句的情况下避免此问题(我尝试过它们 - 它们几乎不会减慢执行速度)。

1 个答案:

答案 0 :(得分:2)

因为SQL Server可以按任何顺序处理JOIN并且

  1. 结转要在最终输出中评估的表达式
  2. 尽早解决表达式,尽早简化为从数据中初步检索
  3. 它无法保证强制应用COLLATE的阶段。因此,您只能将ONCE应用于任何列/表达式。由于您在外部查询中已经有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