【问题标题】:MySQL: multiple groupingMySQL:多个分组
【发布时间】:2010-10-15 10:46:29
【问题描述】:

所以我有一个名为 items 的示例表,其中包含以下列:

  • item_id(整数)
  • person_id(整数)
  • item_name (varchar)
  • item_type (varchar) - 示例:“新闻”、“事件”、“文档”
  • item_date(日期时间)

...和一个表 person,其中包含以下列:“person_id”、“person_name”。

我希望显示每个 item_type 在给定时间段内排名前 2 位提交者的列表(+ 提交的项目的 COUNT() 个)。这基本上是我希望 MySQL 输出的样子:

person_name  | item_type | item_count

Steve Jobs   | document  | 11
Bill Gates   | document  | 6
John Doe     | event     | 4
John Smith   | event     | 2
Bill Jones   | news      | 24
Bill Nye     | news      | 21

如果不对每个 item_type 进行单独的查询,这怎么可能?提前致谢!

【问题讨论】:

    标签: sql mysql group-by


    【解决方案1】:
    SELECT  item_type, person_name, item_count
    FROM    (
            SELECT  item_type, person_name, item_count,
                    @r := IFNULL(@r, 0) + 1 AS rc,
                    CASE WHEN @_item_type IS NULL OR @_item_type <> item_type THEN @r := 0 ELSE 1 END,
                    @_item_type := item_type,
            FROM    (
                    SELECT  @r := 0,
                            @_item_type := NULL
                    ) vars,
                    (
                    SELECT  item_type, person_name, COUNT(*) AS item_count
                    FROM    items
                    GROUP BY
                            item_type, person_name
                    ORDER BY
                            item_type, person_name, item_count DESC
                    ) vo
            ) voi
    WHERE   rc < 3
    

    【讨论】:

    • 与对每个 item_type 使用单独的查询相比,效率如何?
    • 效率更高。如果你有很多 (item_type, person_name) 对,它甚至会非常有效。
    • 取决于您实际拥有的 item_types 数量,但单次访问数据库通常是个好主意,而且此查询看起来对资源的要求不是很高。
    • 如果你把错误代码和文本贴出来会更容易。
    【解决方案2】:

    我认为应该这样做:

    SELECT person_name,item_type,count(item_id) AS item_count
    FROM person
    LEFT JOIN items USING person_id
    GROUP BY person_id
    

    虽然“item_type”列会很狡猾,每一行代表多个项目,而您只显示其中一个项目的 item_type。你可以用“GROUP_CONCAT”列出所有这些,这很有趣。

    【讨论】:

    • 你只是在分组,但他只需要每个 item_type 的前 2 名提交者。
    • 啊,我没有看到每个类别前2的部分。
    【解决方案3】:

    这样的事情应该可以工作:

    SELECT
      p.person_name, i.item_type, COUNT(1) AS item_count
    FROM
      person p
      LEFT JOIN item i
        ON p.person_id = i.person_id
    GROUP BY
      p.person_id,
      i.item_type
    HAVING
      COUNT(1) >= (
        SELECT
          COUNT(1)
        FROM
          item i2
        WHERE
          i2.item_type = i.item_type
        GROUP BY
          i2.person_id
        LIMIT 1,1
      )
    

    【讨论】:

    • 不起作用:对于某些事件类型,即使该类型有更多,也仅返回 1 个最高提交者。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-07-27
    • 2014-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多