【发布时间】:2011-03-02 00:23:24
【问题描述】:
我在列出包含 NULL 列的重复行时遇到问题。让我先说明我的问题。
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
现在如果我想列出所有导致重复的行,我使用这个查询:
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
-------- --------
a b
a b
a b
c d
c d
c d
c d
如您所见,所有包含 NULL 的行都会被过滤。我认为的原因是我使用等号来测试条件(dbo.t.a = duplicate.a AND dbo.t.b = duplicate.b),并且不能使用等号比较NULL。因此,为了在最后一个结果中包含包含 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,您必须在查询中使用许多条件测试语句。随着列数的增加,您在查询中需要的条件测试语句也在惊人地增加。我该如何解决这个问题?
非常感谢。
【问题讨论】:
标签: sql-server sql-server-2005 tsql duplicates