如何在 T-SQL 中处理具有“Union All”但让第二个“Select”始终出现在底部的查询?
Posted
技术标签:
【中文标题】如何在 T-SQL 中处理具有“Union All”但让第二个“Select”始终出现在底部的查询?【英文标题】:How do I Process a Query in T-SQL that has a "Union All" but get the Second "Select" to always appear at the bottom? 【发布时间】:2021-02-24 18:06:34 【问题描述】:我有以下 SQL...
select Policy.[Effective Date], Policy.[Policy #], CLIENT.[NAME], Policy.[Premium]
From Policy, Client
Where Policy.[Effective Date] > '2000-11-11' AND Policy.[Policy Type] <> 'Quote' AND Client.[CLIENTID] = Policy.[CLIENTID]
union all
select null, null, 'Totals', sum(Policy.[Premium])
From Policy, Client
Where Policy.[Effective Date] > '2000-11-11' AND Policy.[Policy Type] <> 'Quote' AND Client.
CLIENTID = Policy.CLIENTID
Order By CLIENT.NAME
但结果看起来像......
【问题讨论】:
Bad Habits to Kick: Using old-style JOINs 【参考方案1】:你需要添加一个额外的固定排序列。这通常非常有效,因为它通常使用Merge Concatenation
、as explained by Paul White。
我建议您不要使用古老且已弃用的 ,
加入语法。我还建议您不要使用需要引用的列名。
select Policy.[Effective Date], Policy.[Policy #], CLIENT.[NAME], Policy.[Premium], 1 AS ordering
From Policy
JOIN Client ON Client.[CLIENTID] = Policy.[CLIENTID]
Where Policy.[Effective Date] > '2000-11-11' AND Policy.[Policy Type] <> 'Quote'
union all
select null, null, 'Totals', sum(Policy.[Premium]), 2
From Policy
JOIN Client ON Client.CLIENTID = Policy.CLIENTID
Where Policy.[Effective Date] > '2000-11-11' AND Policy.[Policy Type] <> 'Quote'
Order By Ordering, CLIENT.NAME
如果您不希望ordering
出现在结果中,那么您需要子查询:
select [Effective Date], [Policy #], [NAME], [Premium]
FROM (
select Policy.[Effective Date], Policy.[Policy #], CLIENT.[NAME], Policy.[Premium], 1 AS ordering
From Policy
JOIN Client ON Client.[CLIENTID] = Policy.[CLIENTID]
Where Policy.[Effective Date] > '2000-11-11' AND Policy.[Policy Type] <> 'Quote'
union all
select null, null, 'Totals', sum(Policy.[Premium]), 2
From Policy
JOIN Client ON Client.CLIENTID = Policy.CLIENTID
Where Policy.[Effective Date] > '2000-11-11' AND Policy.[Policy Type] <> 'Quote'
)
Order By Ordering, CLIENT.NAME
分组集
我注意到您在这里所做的只是第一个结果的汇总。因此,您实际上可以使用GROUPING SETS
syntax 来获得您想要的结果,而无需额外查询。它会更有效率:
select Policy.[Effective Date], Policy.[Policy #], ISNULL(CLIENT.[NAME], 'Totals') AS Name, SUM(Policy.[Premium])
From Policy
JOIN Client ON Client.[CLIENTID] = Policy.[CLIENTID]
Where Policy.[Effective Date] > '2000-11-11' AND Policy.[Policy Type] <> 'Quote'
GROUP BY GROUPING SETS (
(Policy.[Effective Date], Policy.[Policy #], CLIENT.[NAME], Policy.[Premium]),
()
)
ORDER BY
GROUPING_ID(Policy.[Effective Date], Policy.[Policy #], CLIENT.[NAME], Policy.[Premium]),
CLIENT.[NAME]
function GROUPING_ID
为该行中聚合的每一列返回一个 1 位,因此对于我们的总数,我们得到位 1111
,它排在 0000
之后以获取其余结果。
【讨论】:
我喜欢“分组集”。有没有办法为客户名称和高级添加列标题?由于“名称”似乎不起作用 已经编辑了。还有GROUP BY ROLLUP(col1,col2,col3)
,但它为每个级别做了一个小计,这不是你问的
太棒了! 2天我一直试图弄清楚这一点。我见过提到的分组集,但总是作为更复杂场景的一部分。非常感谢!以上是关于如何在 T-SQL 中处理具有“Union All”但让第二个“Select”始终出现在底部的查询?的主要内容,如果未能解决你的问题,请参考以下文章
T-SQL谜题:将表的每一行作为内联函数的输入传递,并使用UNION ALL开发新的堆栈数据集
如何在 Access 中对表的所有列进行 UNION ALL