2013-08-20 43 views
6

Tôi có một bảng như thế này:MySQL trừ hai cột đếm

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 

, vv

Tôi muốn đầu ra như thế này:

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

nơi diff là đếm typeA:success thông điệp - typeB:success tin nhắn. Tôi có thể nhận được số lượng thành công typeA bằng cách sử dụng một cái gì đó như:

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

Tuy nhiên, tôi không thể tìm ra cách đặt một số khác trong đó (đối với typeB) và cũng trừ. Tôi đã thử một cái gì đó như:

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

Nhưng tất nhiên nó không hoạt động hoặc tôi sẽ không hỏi ở đây. :) Lời khuyên nào?

Chỉnh sửa: đã thêm một cột khác. Tôi đã thử hai gợi ý đưa ra, nhưng nó chỉ có vẻ trả về kết quả cho một trong các id, không phải cả hai.

Chỉnh sửa # 2: Tôi đã cố gắng gói truy vấn SELECT với:

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

Tôi đã hy vọng sản lượng sẽ như thế nào:

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

nơi count là số lượng khách hàng mà sự khác biệt giữa typeA: thành công và typeB: thành công là 0.

+0

Re: "Tôi đã cố gắng hai gợi ý được đưa ra, nhưng nó dường như chỉ trả lại kết quả cho một trong các id, không phải cả hai ": Tất cả các câu trả lời đều cho thấy cách tính toán sự khác biệt giữa số đếm; và tôi nghĩ tất cả họ đều rất rõ ràng về điều đó. Thay vì chỉ đơn giản là cố gắng đề xuất mà không đọc chúng, tôi khuyên bạn nên cố gắng học hỏi từ họ, và đặt câu hỏi nếu có những phần bạn không hiểu. : -/ – ruakh

+0

@ruakh Tôi nghĩ tôi đã hiểu các truy vấn tôi đang chạy, vì vậy tại sao tôi lại thử những thứ khác nhau. Tôi nghĩ rằng tôi đã nhận nó với điều này: chọn id, count (*) từ (SELECT id, client, \t COUNT (CASE WHEN msg_type = 'typeA' THEN 1 END) \t - COUNT (CASE WHEN msg_type = 'typeB' THEN 1 END) AS count_a_minus_count_b \t FROM mytable \t đÂU msg_body = 'thành công' \t GROUP \t tHEO khách hàng) như sometable nơi count_a_minus_count_b <1 nhóm bởi id; – user2406467

+0

liên quan đến tổng số tiền http://stackoverflow.com/questions/826365/how-do-i-add-two-count-results-together –

Trả lời

3

COUNT đếm giá trị không null, vì vậy bạn có thể tạo biểu thức không rỗng khi msg_type = 'typeA' và một biểu thức không có giá trị rỗng khi msg_type = 'typeB'. Ví dụ:

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 
; 

(Disclaimer:. Không kiểm tra)

+0

* "(Tuyên bố từ chối trách nhiệm: không được kiểm tra.)" * - Đã làm việc tốt cho tôi. Tôi đã tìm kiếm một cái gì đó như thế này và đã giúp tôi rất nhiều. * Chúc mừng * –

+0

@ Fred-ii-: Rất vui khi được nghe! :-) – ruakh

+0

Cảm ơn :-) Tôi không phải là một guru MySQL nhưng tôi có những khoảnh khắc của tôi. Tuy nhiên, tôi biết cú pháp tốt khi tôi nhìn thấy nó và những gì tôi đã có trong tâm trí đó là một CASE nhưng không biết làm thế nào để sử dụng nó cho những gì tôi muốn thực hiện. Tôi đã phải sửa đổi một chút nhưng cuối cùng thì nó đã trở nên tuyệt vời. * Chúc mừng * –

0

Ở đây bạn đi:

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 
0

Dưới đây là một cách để có được kết quả:

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 

(Các biểu thức trong truy vấn này là MySQL cụ thể, đối với một truy vấn di động hơn, sử dụng một biểu thức CASE ngắn gọn hơn để có được một kết quả tương đương.)


Như ngắn gọn hơn và thay thế obfuscated để trả lại kết quả tương tự:

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 
1

Một cách khác:

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 ; 

Tested tại SQL-Fiddle