Sql server 如何列出可能包含空列的所有重复行?

Sql server 如何列出可能包含空列的所有重复行?,sql-server,sql-server-2005,tsql,duplicates,Sql Server,Sql Server 2005,Tsql,Duplicates,我在列出包含空列的重复行时遇到问题。让我先把问题展示出来 USE [tempdb]; GO IF OBJECT_ID(N'dbo.t') IS NOT NULL BEGIN DROP TABLE dbo.t END GO CREATE TABLE dbo.t ( a NVARCHAR(8), b NVARCHAR(8) ); GO INSERT t VALUES ('a', 'b'); INSERT t VALUES ('a', 'b'); INSERT t VAL

我在列出包含空列的重复行时遇到问题。让我先把问题展示出来

USE [tempdb];
GO

IF OBJECT_ID(N'dbo.t') IS NOT NULL
BEGIN
    DROP TABLE dbo.t
END
GO

CREATE TABLE dbo.t
(
    a NVARCHAR(8),
    b NVARCHAR(8)
);
GO

INSERT t VALUES ('a', 'b');
INSERT t VALUES ('a', 'b');
INSERT t VALUES ('a', 'b');
INSERT t VALUES ('c', 'd');
INSERT t VALUES ('c', 'd');
INSERT t VALUES ('c', 'd');
INSERT t VALUES ('c', 'd');
INSERT t VALUES ('e', NULL);
INSERT t VALUES (NULL, NULL);
INSERT t VALUES (NULL, NULL);
INSERT t VALUES (NULL, NULL);
INSERT t VALUES (NULL, NULL);
GO
现在,我想显示与其他行重复的所有行,我使用以下查询

SELECT a, b
FROM   dbo.t
GROUP
    BY a, b
HAVING count(*) > 1
这将给我们一个结果:

a        b
-------- --------
NULL     NULL
a        b
c        d
a        b
-------- --------
a        b
a        b
a        b
c        d
c        d
c        d
c        d
现在,如果我想列出所有有助于复制的行,我使用以下查询:

WITH
duplicate (a, b) AS
(
    SELECT a, b
    FROM   dbo.t
    GROUP
        BY a, b
    HAVING count(*) > 1
)
SELECT dbo.t.a, dbo.t.b
FROM   dbo.t
       INNER JOIN duplicate
           ON (dbo.t.a = duplicate.a
           AND dbo.t.b = duplicate.b)
这将给我一个结果:

a        b
-------- --------
NULL     NULL
a        b
c        d
a        b
-------- --------
a        b
a        b
a        b
c        d
c        d
c        d
c        d
如您所见,所有包含空值的行都将被过滤。我之所以这样认为是因为我使用等号来测试条件(dbo.t.a=duplicate.a和dbo.t.b=duplicate.b),而空值不能使用等号进行比较。因此,为了在最后一个结果中包含包含null的行,我将前面提到的查询更改为

WITH
duplicate (a, b) AS
(
    SELECT a, b
    FROM   dbo.t
    GROUP
        BY a, b
    HAVING count(*) > 1
)
SELECT dbo.t.a, dbo.t.b
FROM   dbo.t
       INNER JOIN duplicate
           ON (dbo.t.a = duplicate.a
               AND dbo.t.b = duplicate.b)
           OR
           (dbo.t.a IS NULL
               AND duplicate.a IS NULL
               AND dbo.t.b = duplicate.b)
           OR
           (dbo.t.b IS NULL
               AND duplicate.b IS NULL
               AND dbo.t.a = duplicate.a)
           OR
           (dbo.t.a IS NULL
               AND duplicate.a IS NULL
               AND dbo.t.b IS NULL
               AND duplicate.b IS NULL)
这个查询会给出我想要的答案:

a        b
-------- --------
NULL     NULL
NULL     NULL
NULL     NULL
NULL     NULL
a        b
a        b
a        b
c        d
c        d
c        d
c        d
现在我的问题是,正如您所看到的,这个查询只包含两列,为了在最后一个结果中包含null,您必须在查询中使用许多条件测试语句。随着列数的增加,查询中需要的条件测试语句也在惊人地增加。我怎样才能解决这个问题


非常感谢。

您可以改用OVER子句:

select a, b from
(
    select a, b,
        COUNT(*) over (partition by a, b) Cnt
    from dbo.t
) TheResult
where Cnt > 1

这样可以避免所有条件,只需在子查询中添加所有字段并在主选择中检索它们。

如果问题确实存在于等号和
NULL
值中,(将其设置为
OFF
)应该/可以做到这一点

SET ANSI_NULLS OFF