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"

しかし、もちろんうまくいきませんでした。:) 何かアドバイス?

編集:別の列を追加しました。与えられた 2 つの提案を試しましたが、両方ではなく、一方の 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は非 null 値をカウントするため、 の場合は非 null の式を作成し、 の場合は非 null の式を作成でき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
;

(免責事項:テストされていません。)

于 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

結果を取得する 1 つの方法を次に示します。

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 に答える