6

我有一张这样的桌子:

client    msg_type   msg_body  id
------    --------   --------  ---
123       typeA      success   abc
123       typeB      success   abc
456       typeA      success   abc
456       typeB      failure   abc
123       typeA      success   abc
123       typeA      success   abc
789       typeA      success   def
789       typeB      success   def

等等

我想要这样的输出:

client    diff   id
------    ----   ---
 123      2      abc
 456      1      abc
 789      0      def

diff消息数量在哪里typeA:success-typeB:success消息。我可以使用以下方法获得 typeA 成功的计数:

select client, count(*) from mytable
where msg_type="typeA" and msg_body="success"

但是,我不知道如何在其中添加另一个计数(对于 typeB)并减去。我试过类似的东西:

select client, count(*) from mytable
where msg_type="typeA" and msg_body="success" - count(*)
from mytable where msg_type="typeB" and msg_body="success"

但当然它没有用,否则我不会在这里问。:) 有什么建议吗?

编辑:添加了另一列。我尝试了给出的两个建议,但它似乎只返回其中一个 id 的结果,而不是两者。

编辑#2:我尝试用以下方式包装 SELECT 查询:

select id, count(*) from (select ...) as anothertable where count_a_minus_count_b = 0;

我希望输出是这样的:

id    count
---   -----
abc   2
def   1

其中 count 是 typeA:success 和 typeB:success 之差为 0 的客户端数量。

4

4 回答 4

4

COUNT计算非空值,因此您可以构造一个非空 whenmsg_type = 'typeA'的表达式,以及一个非空 when 的表达式msg_type = 'typeB'。例如:

SELECT client,
       COUNT(CASE WHEN msg_type = 'typeA' THEN 1 END) AS count_a,
       COUNT(CASE WHEN msg_type = 'typeB' THEN 1 END) AS count_b,
       COUNT(CASE WHEN msg_type = 'typeA' THEN 1 END)
       - COUNT(CASE WHEN msg_type = 'typeB' THEN 1 END) AS count_a_minus_count_b
  FROM mytable
 WHERE msg_body = 'success'
 GROUP
    BY client
;

(免责声明:未经测试。)

于 2013-08-20T22:26:46.993 回答
2

另一种方式:

SELECT
    d.client, COALESCE(a.cnt, 0) - COALESCE(b.cnt, 0) AS diff, d.id
FROM
    ( SELECT DISTINCT client, id 
      FROM mytable
    ) AS d

  LEFT JOIN
    ( SELECT client, COUNT(*) AS cnt, id
      FROM mytable
      WHERE msg_type = 'typeA' 
        AND msg_body = 'success'
      GROUP BY client, id
    ) AS a
  ON  d.client = a.client
  AND d.id = a.id

  LEFT JOIN
    ( SELECT client, COUNT(*) AS cnt, id 
      FROM mytable
      WHERE msg_type = 'typeB' 
        AND msg_body = 'success'
      GROUP BY client, id
    ) AS b 
  ON  d.client = b.client 
  AND d.id = b.id ;

SQL-Fiddle测试

于 2013-08-20T23:22:06.173 回答
0

干得好:

select client, 
  (sum(case when msg_type='typeA' and msg_body='success' then 1 else 0 end) - 
  sum(case when msg_type='typeB' and msg_body='success' then 1 else 0 end)) as diff
from your_table
group by client
于 2013-08-20T22:26:51.310 回答
0

这是获得结果的一种方法:

SELECT t.client
     , SUM(t.msg_type<=>'typeA' AND t.msg_body<=>'success')
     - SUM(t.msg_type<=>'typeB' AND t.msg_body<=>'success') AS diff
  FROM mytable t
 GROUP BY t.client

(此查询中的表达式是 MySQL 特定的;对于更便携的查询,请使用不太简洁的 CASE 表达式来获得等效结果。)


作为返回相同结果的更简洁和模糊的替代方案:

SELECT t.client
     , SUM((t.msg_body<=>'success')*((t.msg_type<=>'typeA')+(t.msg_type<=>'typeB')*-1)) AS diff
  FROM mytable t
 GROUP BY t.client
于 2013-08-20T22:34:07.997 回答