鉴于下面的示例,为什么在下面的查询2中使用UNION ALL
with两个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;
Run Code Online (Sandbox Code Playgroud)
显然,解决方法对我有用,但我想了解为什么查询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);
Run Code Online (Sandbox Code Playgroud)
我在SQL Server 2014和SQL Server 2008 R2上运行此脚本的结果相同.
因此,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];
Run Code Online (Sandbox Code Playgroud)
你从#T1中选择五个任意选择的记录加上来自#T2的五个任意选择的记录然后你订购这些记录.所以你需要子查询或子句.例如:
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;
Run Code Online (Sandbox Code Playgroud)
因此,您的解决方法根本不是解决方法,而是正确的查询.
您应该在子查询中移动整个 UNION ALL:
Run Code Online (Sandbox Code Playgroud)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
身份证 | 描述 | 不活跃 -: | :---------- | :-------- 4 | 四 | 错误的 6 | 六| 错误的 10 | 10 十 | 错误的 2 | 两个 | 错误的 8 | 八 | 真的
归档时间: |
|
查看次数: |
2403 次 |
最近记录: |