【问题标题】:How to SQL Sum on a field and have a different field in group by section?如何对字段进行 SQL Sum 并按部分分组有不同的字段?
【发布时间】:2013-02-04 00:53:02
【问题描述】:

我有一个这样的表:(请注意,Names 不是唯一的,可以重复,而 Personal_ID 是唯一的)。

ID    SourceID     Personal_ID     Name     NumberOfPurchases 
1      4            1001           Alex           10
2      2            1002           Sara            5
3      4            1001           Alex            12
4      1            1003           Mina            200
5      2            1002           Sara            20  
6      2            1001           Alex            64

现在需要做的是根据给定的 SourceID 获取每个人的购买总数。这样我们就有sourceId = 4 的结果为:

        Name        Total Number of Purchases
 1.     Alex                 22

对于 SourceID = 2

        Name        Total Number of Purchases
1.      Alex                 64
2.      Sara                 25

为此,我想出了这样的东西:

SELECT Name,Sum(NumberOfPurchases) AS Total
FROM    tblTEST
GROUP BY (Personal_ID)
HAVING (SOURCEID = @id)

但这显然是错误的。我被困在这里,如果我将其他字段添加到group-by clause,结果将完全不同,如果我不这样做,这个选择命令将不起作用。我怎样才能达到这样的结果?

【问题讨论】:

    标签: sql-server select group-by aggregate-functions having-clause


    【解决方案1】:

    我猜这里的问题是你的SELECT 子句中有Name,但你在Personal_ID 上分组。如果您也将Name 明确添加到您的GROUP BY 子句中,这可能会有所帮助。如果一切顺利,Name 的功能将由Personal_ID 无论如何决定。

    您还应该将过滤器放在 WHERE 子句中的 SourceID 上,例如 Lucero says。所以你的查询应该是这样的:

    SELECT   Name
             ,Sum(NumberOfPurchases) AS Total
    FROM     tblTEST
    WHERE    SOURCEID = @id
    GROUP BY Personal_ID, Name;
    

    看看这个Fiddle

    澄清一下:如果您使用SUM() 之类的聚合函数,则SELECT 子句中的所有其他 内容也应该在GROUP BY 子句中。但是您不想仅在 Name 上进行分组,因为在您的情况下它不是唯一的。这就是为什么在 GROUP BY 子句中同时包含 Personal_ID Name 的原因。当GROUP BY 中缺少Name 时,查询将不会执行。而且您要添加 Personal_ID 以确保并非所有 Sara 都放在一个大 Sara 组中,而是根据 Personal_ID 进行分组。

    【讨论】:

    • 非常感谢,但是名字不是唯一的,所以他们可以重复,所以查询不会给我预期的结果!
    • HAVING 仅将聚合函数调用的结果与某个值 (MSDN) 进行比较。这不会编译。
    • @Hossein:但是 Personal_ID 和名称的组合唯一的,对吗?或者您希望 Alex 组中的不同 Alexes 和 Sara 组中的 Sara 不同??
    • @IvanG:你是对的,相应地改变了它。起初我只是查看了GROUP BY 子句中缺少的Name
    • 感谢 Josien :) 是的,这种组合也是独一无二且可行的
    【解决方案2】:

    这样的?

    SELECT Name, SUM(NumberOfPurchases) AS Total
    FROM tblTEST
    WHERE (SourceID = @id)
    GROUP BY Name
    

    注意:WHERE 过滤之前分组,HAVING 过滤之后分组。

    【讨论】:

    • 谢谢,但名字不是唯一的,这就是为什么我使用 Personal_ID 来让每个人都唯一购买
    • Name 列不适合分组,名称不是唯一的。如果您有另一个名为“Alex”的用户使用不同的Personal_ID,则尽管有两个不同的人,但他们的所有购买都将汇总在一起。
    • @IvanG,虽然您的论点是正确的,但我遵循了 OP 在原始查询中选择的列。由于从未选择过 ID,因此带有两者的 GROUP BY 将产生具有相同(无法区分)名称和购买次数的多行,这也是无稽之谈。我的回答是解决过滤方面的问题。
    【解决方案3】:

    你可以试试这个:

    SELECT  names.Name
            , names.Personal_ID
            , grouped.Total
    FROM    (
                SELECT  SourceID
                        , Personal_ID
                        , SUM(NumberOfPurchases) AS Total
                FROM    tblTEST
                GROUP BY 
                        SourceID, Personal_ID
    ) grouped
    JOIN    (
    
            SELECT  DISTINCT
                    Personal_ID
                    , Name
            FROM    tblTEST
    ) names ON      names.Personal_ID = grouped.Personal_ID
    WHERE           SourceID = @id
    

    这是一个SQL Fiddle

    在测试数据中,我添加了另一条记录,其中包含名为“Alex”的人,现在有两个同名的人,这表明无法使用 Name 列进行分组,因为它不是唯一的。我还在选择列表中添加了Personal_ID,以便区分同名的人。

    【讨论】:

    • :非常感谢,太好了,我对选择哪个作为答案持怀疑态度,因为 Josiens 的解决方案更简洁,我选择了那个。我也喜欢你的 SQL Fiddle 链接太棒了。总而言之,我只是想向您表达我对您的帮助深表感谢;)​​再次感谢您:)
    • 不客气 :) Josien 的解决方案很好且高效,因为它按Personal_IDName 分组。只有一个名字与一个人的 ID 相关联,所以它很简单,而且可以按预期工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-12
    • 1970-01-01
    相关资源
    最近更新 更多