【问题标题】:MySQL - Group and total, but return all rows in each groupMySQL - 组和总计,但返回每个组中的所有行
【发布时间】:2015-01-26 20:22:03
【问题描述】:

我正在尝试编写一个查询,该查询在特定日期范围内每次在我的表中出现同一个人时查找。然后,它将这个人分组并汇总他们在特定范围内的支出。如果他们的消费习惯大于 X 金额,则返回此人在指定日期范围内的每一行。不仅仅是分组的总金额。这是我目前所拥有的:

SELECT member_id, 
SUM(amount) AS total 
FROM `sold_items` 
GROUP BY member_id 
HAVING total > 50

这是检索正确的总数和返回的成员花费超过 50 美元,但不是每一行。只是每个成员的总数和他们的总数。我目前正在查询整个表,我还没有添加日期范围。

【问题讨论】:

  • 不可能。当您group 时,该组的所有成员行都将折叠成一个代表行。如果你想要原始的成员行,那么你不能使用group by
  • 同意。在这里,您希望在查询上有一个应用层,以根据报告的要求提供小计和细分。
  • 您可以JOIN这个子查询与原表返回所有相关行。
  • 我可以使用SQL Server中的OVER()函数实现这个结果,不知道在mySQL中是否有类似的东西。
  • 我正在用 PHP 编写后端。我正在考虑将超过 X 数量的成员返回到我的 PHP 模型,然后使用 IN 运行第二个查询并编写一个循环以包含在第一个查询中找到的所有成员。这是不好的做法吗?

标签: mysql


【解决方案1】:

JOIN这个子查询与原表:

SELECT si1.*
FROM sold_items AS si1
JOIN (SELECT member_id
      FROM sold_items
      GROUP BY member_id
      HAVING SUM(amount) > 50) AS si2
ON si1.member_id = si2.member_id

一般规则是子查询按其选择的相同列分组,然后使用相同的列将其与原始查询连接。

【讨论】:

  • 这似乎解决了我的问题!谢谢!而且我从来不知道我可以用 JOIN 编写这样的嵌套选择语句。非常棒。
  • 它不起作用,它不会为我返回所有结果:pastebin.com/DhvrmNsq 查询应该返回重复的结果(相同的设备和相同的时间)但它错过了超过 2 个实例的重复.
  • 您的子查询不正确。它只是从每个组中选择一个 ID,而不是所有 ID。您需要选择要分组的相同列,然后在联接中使用这些列。
  • @singe3 你不应该因为你的版本错误而投反对票。
  • 好的,谢谢你的解释,很抱歉投反对票:)
【解决方案2】:
SELECT member_id, amount
FROM sold_items si
INNER JOIN (SELECT member_id, 
SUM(amount) AS total 
FROM `sold_items` 
GROUP BY member_id 
HAVING total > 50) spenders USING (member_id)

您已经构建的查询可以用作临时表来连接。如果 member_id 不是表上的索引,则随着规模的扩大,这将变慢。 “spenders”这个词是一个表别名,您可以使用任何有效的别名来代替它。

【讨论】:

    【解决方案3】:

    有一些语法可以得到你正在寻找的结果,这里有一个使用内连接来确保返回的所有行在 group by 返回的列表中都有一个 member_id 并且每个 a 重复总数某些成员有:

    SELECT si.*, gb.total from sold_items as si, (SELECT member_id as mid, 
    SUM(amount) AS total 
    FROM `sold_items` 
    GROUP BY member_id 
    HAVING total > 50) as gb where gb.mid=si.member_id;
    

    【讨论】:

    • 请不要在答案中使用隐式连接。我们尝试推广 ANSI 连接。
    • 我很抱歉,有道理。
    【解决方案4】:

    我认为这可能会有所帮助:

    SELECT 
        member_id, 
        SUM(amount) AS amount_value,
        'TOTAL' as amount_type
    FROM 
        `sold_items` 
    GROUP BY 
        member_id 
    HAVING 
        SUM(amount) > 50
    
    UNION ALL
    
    SELECT 
        member_id,
        amount AS amount_value,
        'DETAILED' as amount_type
    FROM 
        `sold_items` 
        INNER JOIN
        (
            SELECT 
                A.member_id, 
                SUM(amount) AS total 
            FROM 
                `sold_items` A 
            GROUP BY 
                member_id 
            HAVING 
                total <= 50
        ) AS A
        ON `sold_items`.member_id = A.member_id 
    

    上述查询的结果应如下所示:

    member_id     amount_value    amount_type
    ==========================================
    1             55              TOTAL
    2             10              DETAILED
    2             15              DETAILED
    2             10              DETAILED
    

    所以amount_type 列将区分两个特定的成员组

    【讨论】:

      【解决方案5】:

      您可以使用EXISTS 进行子查询作为替代:

      select *
      from sold_items t1
      where exists (
          select * from sold_items t2
          where t1.member_id=t2.member_id
          group by member_id
          having sum(amount)>50
      )
      

      参考:http://dev.mysql.com/doc/refman/5.7/en/exists-and-not-exists-subqueries.html

      【讨论】:

        【解决方案6】:

        如果您需要按多列分组,您可以将复合标识符连接结合使用按子查询分组

        select id, key, language, group
          from translation
        
          --query all key-language entries by composite identifier...
          where concat(key, '_', language) in (
        
            --by lookup of all key-language combinations...
            select concat(key, '_', language)
            from translation
            group by key, language
            
            --that occur more than once
            having count(*) > 1
        
          )
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-06-13
          • 1970-01-01
          • 2011-09-02
          • 2021-08-14
          相关资源
          最近更新 更多