连接多个nvarchar列

时间:2015-05-31 16:18:30

标签: sql-server tsql

我有一张这样的表:

CREATE TABLE [dbo].[Table](
    [Id] [INT] IDENTITY(1,1) NOT NULL,
    [A] [NVARCHAR](150) NULL,
    [B] [NVARCHAR](150) NULL,
    [C] [NVARCHAR](150) NULL,
    [D] [NVARCHAR](150) NULL,
    [E] [NVARCHAR](150) NULL,
 CONSTRAINT [con] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

并查找要加入此表格的表现。

选项1 - 将所有字符串合并到nvarchar主键中,然后执行:

Source.[A] + Source.[B] + Source.[C] + Source.[D] + Source.[E] = Table.PKString

据我所知,这是不好的做法。

选项2 - 使用:

Source.[A] + Source.[B] + Source.[C] + Source.[D] + Source.[E] = Target.[A] + Target.[B] + Target.[C] + Target.[D] + Target.[E]

选项3 - 使用:

Source.[A] = Target.[A] And
...
Source.[E] = Target.[E]

1 个答案:

答案 0 :(得分:5)

您的选项1无效,因为它会将('ab','c')视为等于('a','bc')

此外,您的列可以为空,并且连接null会产生null。

由于可空性,您无法将所有列合并到nvarchar主键中,即使没有这样,您仍然会面临失败的风险,因为最大长度为1,500字节,远远超过最大索引键列大小。

由于类似的长度原因,使用所有列的复合索引也不起作用。

您可以创建一个计算列,该列使用所有这5个列值作为输入来计算校验和或散列值和索引。

ALTER TABLE [dbo].[Table]
  ADD HashValue AS CAST(hashbytes('SHA1', ISNULL([A], '') + ISNULL([B], '')+ ISNULL([C], '')+ ISNULL([D], '')+ ISNULL([E], '')) AS VARBINARY(20));


CREATE INDEX ix
  ON [dbo].[Table](HashValue)
  INCLUDE ([A], [B], [C], [D], [E]) 

然后在哈希冲突的情况下,在其他5列的剩余谓词的连接中使用它。

如果您希望NULL比较相等,则可以使用

SELECT *
FROM   [dbo].[Table1] source
       JOIN [dbo].[Table2] target
         ON source.HashValue = target.HashValue
            AND EXISTS(SELECT source.A,
                              source.B,
                              source.C,
                              source.D,
                              source.E
                       INTERSECT
                       SELECT target.A,
                              target.B,
                              target.C,
                              target.D,
                              target.E) 

请注意,上面创建的索引基本上会重现整个表格,因此如果您的查询需要覆盖,则可能需要考虑创建为群集。