鉴于下面的示例,为什么在下面的查询2中使用UNION ALL
和两个SELECT TOP 5
语句似乎不尊重ORDER BY
子句?
查询1返回预期结果,但不包括所需的联合。 查询2演示了意外行为。 查询3是我目前用于获得所需结果的解决方法。
CREATE TABLE #T1 ([ID] int IDENTITY(1,1), [Description] varchar(100), [Inactive] bit);
CREATE TABLE #T2 ([ID] int IDENTITY(1,1), [Description] varchar(100), [Inactive] bit);
INSERT INTO #T1([Description], [Inactive]) VALUES ('One', 1);
INSERT INTO #T1([Description], [Inactive]) VALUES ('Two', 0);
INSERT INTO #T1([Description], [Inactive]) VALUES ('Three', 1);
INSERT INTO #T1([Description], [Inactive]) VALUES ('Four', 0);
INSERT INTO #T1([Description], [Inactive]) VALUES ('Five', 1);
INSERT INTO #T1([Description], [Inactive]) VALUES ('Six', 0);
INSERT INTO #T1([Description], [Inactive]) VALUES ('Seven', 1);
INSERT INTO #T1([Description], [Inactive]) VALUES ('Eight', 1);
INSERT INTO #T1([Description], [Inactive]) VALUES ('Nine', 1);
INSERT INTO #T1([Description], [Inactive]) VALUES ('Ten', 0);
-- Query 1, works as expected giving all 4 records with Inactive = 0 plus one more
SELECT TOP 5 [ID], [Description], [Inactive]
FROM #T1
ORDER BY [Inactive], [Description];
-- Query 2, does not work as expected, as only 2 of the Inactive = 0 records are present
SELECT TOP 5 [ID], [Description], [Inactive]
FROM #T1
UNION ALL
SELECT TOP 5 [ID], [Description], [Inactive]
FROM #T2
ORDER BY [Inactive], [Description];
-- Query 3, Workaround to produce desired results
WITH T1 AS (
SELECT TOP 5 [ID], [Description], [Inactive]
FROM #T1
ORDER BY [Inactive], [Description]
),
T2 AS (
SELECT TOP 5 [ID], [Description], [Inactive]
FROM #T2
ORDER BY [Inactive], [Description]
)
SELECT [ID], [Description], [Inactive] FROM T1
UNION ALL
SELECT [ID], [Description], [Inactive] FROM T2
ORDER BY [Inactive], [Description];
DROP TABLE #T1;
DROP TABLE #T2;
显然,解决方法对我有用,但我想了解为什么查询2没有达到我的预期。如果您想知道我为什么要打扰空表#T2
,结果实际上受到我的生产示例中的WHERE
子句的限制 - 但是这里将其留空是为了提供一个可比较的例子,没有费心去填充它。
如果您使用以下内容填充#T2
,我会发现结果同样奇怪 - 查询2仅显示Inactive = 0
的四个结果。
INSERT INTO #T2([Description], [Inactive]) VALUES ('Eleven', 1);
INSERT INTO #T2([Description], [Inactive]) VALUES ('Twelve', 0);
INSERT INTO #T2([Description], [Inactive]) VALUES ('Thirteen', 1);
INSERT INTO #T2([Description], [Inactive]) VALUES ('Fourteen', 0);
INSERT INTO #T2([Description], [Inactive]) VALUES ('Fifteen', 1);
INSERT INTO #T2([Description], [Inactive]) VALUES ('Sixteen', 0);
INSERT INTO #T2([Description], [Inactive]) VALUES ('Seventeen', 1);
INSERT INTO #T2([Description], [Inactive]) VALUES ('Eighteen', 1);
INSERT INTO #T2([Description], [Inactive]) VALUES ('Nineteen', 1);
INSERT INTO #T2([Description], [Inactive]) VALUES ('Twenty', 0);
我在SQL Server 2014和SQL Server 2008 R2上运行此脚本的结果相同。
答案 0 :(得分:6)
Union查询的工作原理是:执行查询,然后应用order by子句。所以用
SELECT TOP 5 [ID], [Description], [Inactive]
FROM #T1
UNION ALL
SELECT TOP 5 [ID], [Description], [Inactive]
FROM #T2
ORDER BY [Inactive], [Description];
从#T1中选择五个任意选择的记录加上来自#T2的五个任意选择的记录然后您订购这些记录。所以你需要子查询或子句。 E.g:
SELECT * FROM
(
(
SELECT TOP 5 [ID], [Description], [Inactive]
FROM #T1
ORDER BY [Inactive], [Description]
)
UNION ALL
(
SELECT TOP 5 [ID], [Description], [Inactive]
FROM #T2
ORDER BY [Inactive], [Description]
)
) t;
因此,您的解决方法根本不是解决方法,而是正确的查询。
答案 1 :(得分:0)
您应该在子查询中移动整个UNION ALL:
SELECT * FROM (SELECT TOP 5 [ID], [Description], [Inactive] FROM #T1 ORDER BY [Inactive], [Description] UNION ALL SELECT TOP 5 [ID], [Description], [Inactive] FROM #T2 ORDER BY [Inactive], [Description]) T3 ORDER BY [Inactive], [Description]; GO
ID | Description | Inactive -: | :---------- | :------- 4 | Four | False 6 | Six | False 10 | Ten | False 2 | Two | False 8 | Eight | True
答案 2 :(得分:0)
查询#2和#3之间存在重大差异 - #T1上的ORDER BY子句。
如果你没有指定ORDER BY原因,那么拇指规则是-in SQL查询," TOP"将只返回随机记录集。在你得到这些"随机"行,排序发挥作用。因此,没有"适当的"排序发生。