如何选择 n 列和一个 SUM,同时仅按一些非聚合列分组?
Posted
技术标签:
【中文标题】如何选择 n 列和一个 SUM,同时仅按一些非聚合列分组?【英文标题】:How to SELECT n columns and a SUM, while only grouping by some of the non-aggregate columns? 【发布时间】:2018-11-28 03:39:34 【问题描述】:我的 SQL 基础知识在这方面可能有点偏离,但我会很感激任何帮助。
正如问题所述,我正在尝试执行以下操作(不使用 Concat(),因为我坚持使用 SQL Server 2008 R2):
SELECT name, phone, (id1+'-'+id2+'-'+id3) as id
,SUM(CASE WHEN code IN ('00','01','02','03','04','05')
THEN expenses ELSE 0 END) AS sum_expenses
FROM random_table
GROUP BY id1, id2, id3
此查询将引发错误,因为姓名和电话未分组。我正在寻找一种解决方案,在该解决方案中,我可以按他们的 id 对总费用进行分组,同时将姓名和电话保留为非聚合、非分组列,因为它们是为每个 id 行保留的基本字段。我还没有在 *** 上找到明确的答案。
我在尝试解决此问题时考虑过但不确定是否可行(/甚至适用)的解决方案:1)在 Select 语句中对 Sum 进行子查询; 2) 使用公共表表达式将 Sum 与主查询分开,3) 为 id 字段和 Sum 创建一个单独的表,然后使用 id 作为公共字段将其重新连接。
请注意,在 GROUP By 中不包括姓名和电话的原因是我需要按唯一 id 行对数据进行分组
谢谢
【问题讨论】:
为什么不能使用GROUP BY id1, id2, id3, name, phone
?
以上只是一个基本的例子;还有更多字段,其中一些字段每个 id 行有多个值。我需要按唯一 id 行对数据进行分组。
【参考方案1】:
窗口函数、交叉应用、公用表表达式都是可行的选择。
这是一个使用公用表表达式和交叉应用的示例。
WITH CTE
AS
(
SELECT
id1,
id2,
id3,
(id1 + '-' + id2 + '-' + id3) AS id,
SUM(CASE WHEN code IN ('00','01','02','03','04','05') THEN expenses ELSE 0 END) AS sum_expenses
FROM random_table
GROUP BY id1, id2, id3
)
SELECT
ca.name,
ca.phone,
cte.id,
cte.sum_expenses
FROM CTE AS cte
CROSS APPLY (
SELECT TOP 1
name,
phone
FROM random_table AS rt
WHERE rt.id1 = cte.id1
AND rt.id2 = cte.id2
AND rt.id3 = cte.id3
) AS ca
【讨论】:
谢谢;这正是我想要的。我以前没听说过 CROSS APPLY。【参考方案2】:group by 子句中提到的列在您的输出中是唯一的。
我建议你看看窗口函数。
例如:
select name,phone,(id1+'-'+id2+'-'+id3) as id
,sum(CASE WHEN code IN ('00','01','02','03','04','05')
THEN expenses
ELSE 0
END) over(partition by id1, id2, id3) as summed_by_id
from random_table
【讨论】:
谢谢,我也会研究窗口函数以备将来查询。【参考方案3】:试试这个...
SELECT name, phone, (id1+'-'+id2+'-'+id3) as id
,SUM(CASE WHEN code IN ('00','01','02','03','04','05')
THEN expenses ELSE 0 END) over (partition by id1, id2, id3) AS sum_expenses
FROM random_table
【讨论】:
以上是关于如何选择 n 列和一个 SUM,同时仅按一些非聚合列分组?的主要内容,如果未能解决你的问题,请参考以下文章
SQL Server SUM IF 使用具有多个条件的窗口函数