MySQL减去两个计数列

时间:2013-08-20 22:21:42

标签: mysql sql

我有一张这样的表:

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

其中difftypeA: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 个答案:

答案 0 :(得分:3)

COUNT计算非空值,因此您可以在msg_type = 'typeA'时构造一个非空的表达式,并在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
;

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

答案 1 :(得分: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

进行测试

答案 2 :(得分: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

答案 3 :(得分: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