【问题标题】:Mysql multi count in one queryMysql 一次查询多次计数
【发布时间】:2011-03-19 16:52:24
【问题描述】:

如何使用不同的查询条件计算一张表中两列的记录?

表格如下:

   user_id  |   date     | status
------------------------------
      1     | 2011-01-02 |   1
      2     | 2011-01-03 |   1
      3     | 2011-01-02 |   0
      4     | 2011-01-03 |   1
      1     | 2011-01-02 |   1

我想在一个查询中计算两个值。第一个是按状态分组的 user_id 组数,第二个是按日期分组的 user_id 组数。

我该怎么做?

【问题讨论】:

  • 使用类似 SELECT COUNT ...
  • 请提供您预期输出的示例,因为每个状态的计数与每个日期的计数无关。笛卡尔积是唯一的结果。

标签: mysql sql aggregate-functions


【解决方案1】:

在同一个查询中不能有不同的 GROUP BY 子句——每个计数都必须在一个独立的查询中。

但是您可以使用子选择(SELECT 子句中的子查询)在单个查询/结果集中返回输出:

   SELECT COUNT(a.user_id) AS numUsersPerStatus,
          (SELECT COUNT(b.user_id)
             FROM YOUR_TABLE b
         GROUP BY b.date) AS numUsersPerDate
    FROM YOUR_TABLE a
GROUP BY a.status

【讨论】:

  • 如果在Select Column中使用子查询,它应该只返回1行1列,numUsersPerDate会返回多行不同的日期?我认为这个查询可以根据数据给出运行时错误?如果我错了,请纠正我.....
  • @Nitin Midha:不,这不会导致运行时错误。每个状态计数都会重复 numUsersPerDate - 结果将是笛卡尔积。
  • 那么我希望,它应该在带有交叉连接的 from 子句中......这是 SQL Server 和 MySQL 之间已知的区别吗?据我记得,在 SQL Server 中它会给出一个错误...
  • @Nitin Midha:CROSS JOIN 只是用于生成笛卡尔积的 ANSI-92 语法。不,提供的查询也不会在 SQL Server 上产生错误 - 子选择非常常见,因为 ANSI-89 不支持 OUTER 联接(如果有链接条件,则此示例将使用 LEFT JOIN 重写表)。
【解决方案2】:

没有

您应该使用两个查询。使用单个查询执行此操作没有任何优势。

如果你真的想要这样做,你可以试试这个:

SELECT 'date' AS grptype, date AS grp, COUNT(DISTINCT user_id) AS cnt
FROM yourtable
GROUP BY date
UNION ALL
SELECT 'status' AS grptype, status AS grp, COUNT(DISTINCT user_id) AS cnt
FROM yourtable
GROUP BY status

结果:

grptype grp cnt 日期 2011-01-02 2 日期 2011-01-03 2 状态 0 1 状态 1 3

但是我强烈建议不要这样做。您需要两个不同且不相关的结果集,因此您应该使用两个单独的查询。

【讨论】:

  • UNION 原样不起作用 - 日期和状态列是不同的数据类型。并且您希望将其用作派生表/内联视图,以便最终使用 MAX 压缩成更少的行。
  • 你为什么不建议这样做?
  • @rahmanisback:因为这是对 SQL 的滥用。每次在单个列中混合数据类型时,独角兽就会死亡。在大多数数据库中,甚至不允许这样的事情。由于类型转换,MySQL 允许它。但仅仅因为你可以并不意味着你应该
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-12
  • 1970-01-01
  • 2020-12-25
  • 1970-01-01
  • 2015-05-02
  • 2011-07-24
  • 1970-01-01
相关资源
最近更新 更多