带有 UNION 子句的 ORDER BY
Posted
技术标签:
【中文标题】带有 UNION 子句的 ORDER BY【英文标题】:ORDER BY with UNION clause 【发布时间】:2020-11-26 09:49:34 【问题描述】:无论我在哪里搜索,我都发现下面的代码应该可以工作。
SELECT id, name, age FROM A
UNION
SELECT id, name, age FROM B
ORDER BY name
我的查询是在特定日期之间搜索数据库中的每个值,然后只选择该指定日期之前的几个值。这个查询本身是有效的,但我想按某个列对其进行排序,我得到了错误:
如果语句包含 UNION、INTERSECT 或 EXCEPT 运算符,则 ORDER BY 项必须出现在选择列表中
这是我的代码:
DECLARE @inidate DATE = '20201001', @findate DATE = '20201031'
SELECT bo.id, bo.date, bo.status
FROM BO (nolock)
JOIN BO2 (nolock) ON BO2.bo2stamp = BO.bostamp
WHERE (BO.date BETWEEN @inidate AND @findate)
AND (BO.tabela1 IN ('INSTALED','CANCELED'))
UNION
SELECT bo.id, bo.date, bo.status
FROM BO (nolock)
JOIN BO2 (nolock) ON BO2.bo2stamp = BO.bostamp
WHERE (BO.date < @inidate)
AND (BO.tabela1 NOT IN ('INSTALED','CANCELED'))
ORDER BY bo2.u_registration_date
我已经尝试了此处显示的代码,但在ORDER BY
上出现错误
预期的 AS、ID 或 QUOTED_ID
SELECT *
FROM
([my query])
ORDER BY bo2.u_registration_date
我也试过
SELECT *
FROM ([1st query])
UNION
SELECT *
FROM ([2nd query])
ORDER BY bo2.u_registration_date
【问题讨论】:
错误告诉你问题;当SELECT
不在时,您不能通过u_registration_date
订购。如果您必须具有该顺序的数据但未公开,则子查询中的UNION
查询带有列,然后将其排除在外部查询中,但对其进行排序。跨度>
您也真的需要针对每张桌子的NOLOCK
提示吗?您确实了解它的作用,对吗? NOLOCK
不是一个神奇的“更快”按钮,很容易导致您的结果不正确。 Bad habits : Putting NOLOCK everywhere
错误信息很清楚,你不能按 u_registration_date 订购,因为你没有选择那一列。
你可以用UNION ALL
代替吗?还是您想要/需要消除重复项?
有人告诉我使用nolock
,因为如果我有一个很棒的数据库,我可能会以某种方式阻止这些表并且无法再访问它。我信任这个人,因为我对 SQL 的了解非常有限,大约 2 个月前我就开始学习了。
【参考方案1】:
您需要将union
放在子查询中,并在外部查询中排序。此外,子查询需要返回您要用于排序的列。
SELECT *
FROM (
SELECT bo.id, bo.date, bo.status, bo2.u_registration_date
FROM BO
JOIN BO2 ON BO2.bo2stamp = BO.bostamp
WHERE BO.date BETWEEN @inidate AND @findate AND BO.tabela1 IN ('INSTALED','CANCELED')
UNION
SELECT bo.id, bo.date, bo.status, bo2.u_registration_date
FROM BO
JOIN BO2 ON BO2.bo2stamp = BO.bostamp
WHERE BO.date < @inidate AND BO.tabela1 NOT IN ('INSTALED','CANCELED')
) t
ORDER BY u_registration_date
请注意,在这里使用UNION
没有多大意义。这两个成员仅在日期过滤器上有所不同,因此在功能上您的查询等同于:
SELECT bo.id, bo.date, bo.status, bo2.u_registration_date
FROM BO
JOIN BO2 ON BO2.bo2stamp = BO.bostamp
WHERE BO.date < @findate AND BO.tabela1 NOT IN ('INSTALED','CANCELED')
ORDER BY bo2.u_registration_date
【讨论】:
...尽管您可以评论说,在某些情况下,联合版本可能运行得更快,具体取决于索引方案。但是无论哪种方式都可以为您的答案 +1。 如果我不使用UNION
,我的查询不会在我首先选择的日期之间返回任何数据,它不会显示我在日期内的任何数据指定
UNION
不过滤数据,@pauLo_0liveira。它只是将 2+ 个具有相同定义的数据集组合在一起,并从 2+ 个数据集中返回 DISTINCT
行。如果UNION
查询返回行,那么至少一个内部查询也会返回。
我在括号后的选择和别名中都添加了bo2.u_registration_date
,但现在我的错误是它没有找到bo2.u_registration_date
,我尝试在select *
之后添加它,但是让它识别我需要在括号前添加BO2
。
成功了,我是通过bo2.u_registration_date
订购的,而不仅仅是u_registration_date
。非常感谢以上是关于带有 UNION 子句的 ORDER BY的主要内容,如果未能解决你的问题,请参考以下文章
我可以在 SQL 中使用 UNION 子句的查询中添加 ORDER BY 子句吗?
如何在 UNION 之间的 SQL 中放置 ORDER BY 子句
在 sql 查询中使用 group/order by 和 union 子句