如何选择 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,同时仅按一些非聚合列分组?的主要内容,如果未能解决你的问题,请参考以下文章

最大子列和(在线处理,复杂度O(n))

SQL Server SUM IF 使用具有多个条件的窗口函数

Gym - 100735E Restore

SQL - 将聚合表与非聚合表连接起来

如何在 Hypersql 数据库(HSQLDB)中选择多列但仅按一列分组?

Maximum Subsequence Sum - 最大子列和问题_C语言实现