最好在您的问题中包含代码,而不是模棱两可的文本数据,以便我们都使用相同的数据。这是我假设的示例架构和数据:
CREATE TABLE tbl_data (
id INT NOT NULL,
code_1 CHAR(2),
code_2 CHAR(2)
);
INSERT INTO tbl_data (
id,
code_1,
code_2
)
VALUES
(1, 'AB', 'BC'),
(2, 'BC', NULL),
(3, 'DE', 'EF'),
(4, NULL, 'BC');
正如Blorgbeard评论的那样,DISTINCT
您的解决方案中的子句是不必要的,因为UNION
运算符消除了重复的行。有一个UNION ALL
运算符不消除重复,但在这里不合适。
不使用该子句重写查询DISTINCT
是解决此问题的好方法:
SELECT code_1
FROM tbl_data
WHERE code_1 IS NOT NULL
UNION
SELECT code_2
FROM tbl_data
WHERE code_2 IS NOT NULL;
两列在同一个表中并不重要。即使列在不同的表中,解决方案也是相同的。
如果您不喜欢两次指定相同过滤子句的冗余,您可以在过滤之前将联合查询封装在虚拟表中:
SELECT code
FROM (
SELECT code_1
FROM tbl_data
UNION
SELECT code_2
FROM tbl_data
) AS DistinctCodes (code)
WHERE code IS NOT NULL;
我发现第二个的语法更丑陋,但它在逻辑上更整洁。但是哪一个表现更好呢?
我创建了一个sqlfiddle来演示 SQL Server 2005 的查询优化器为两个不同的查询生成相同的执行计划:
如果 SQL Server 为两个查询生成相同的执行计划,那么它们实际上在逻辑上是等效的。
将上述内容与您问题中查询的执行计划进行比较:
该DISTINCT
子句使 SQL Server 2005 执行冗余排序操作,因为查询优化器不知道DISTINCT
在第一个查询中过滤掉的任何重复项都会被UNION
后面的查询过滤掉。
这个查询在逻辑上与其他两个是等价的,但是冗余操作使其效率降低。在大型数据集上,我希望您的查询需要比这里的两个更长的时间才能返回结果集。不要相信我的话;在您自己的环境中进行实验以确保!