2010-08-30 31 views
9
bảng

cơ sở dữ liệu như truy vấntrở lại đếm 0 với nhóm mysql bởi

============================ 
= suburb_id | value 
= 1   | 2 
= 1   | 3 
= 2   | 4 
= 3   | 5 

đây là

SELECT COUNT(suburb_id) AS total, suburb_id 
    FROM suburbs 
where suburb_id IN (1,2,3,4) 
GROUP BY suburb_id 

Tuy nhiên, trong khi tôi chạy truy vấn này, nó không cung cấp cho COUNT (suburb_id) = 0 khi suburb_id = 0 vì ở vùng ngoại ô bảng, không có suburb_id 4, tôi muốn truy vấn này trả về 0 cho suburb_id = 4, như

============================ 
= total  | suburb_id 
= 2   | 1 
= 1   | 2 
= 1   | 3 
= 0   | 4 
+0

Bạn có một bảng khác với thông tin cho tất cả các vùng ngoại ô không? Hoặc là surburb 4 Sir Not-Appearing-In-This-Database? – Powerlord

Trả lời

10

Một GROUP BY cần hàng để làm việc với, vì vậy nếu bạn không có hàng cho một thể loại nhất định, bạn sẽ không nhận được số lượng. Hãy suy nghĩ về mệnh đề where như giới hạn các hàng nguồn trước khi chúng được nhóm lại với nhau. Mệnh đề where không cung cấp danh sách các loại để nhóm theo.

Việc bạn có thể làm là viết truy vấn để chọn các danh mục (ngoại ô) rồi thực hiện đếm trong truy vấn phụ. (Tôi không chắc chắn những gì hỗ trợ MySQL cho điều này là tương tự)

Cái gì như:

SELECT 
    s.suburb_id, 
    (select count(*) from suburb_data d where d.suburb_id = s.suburb_id) as total 
FROM 
    suburb_table s 
WHERE 
    s.suburb_id in (1,2,3,4) 

(MSSQL, lời xin lỗi)

+0

+1 cho trường hợp đơn giản, nhưng khi bạn cần kết hợp một số truy vấn phức tạp hơn, vui lòng xem câu trả lời của tôi. – Upgradingdave

+0

Đây chính xác là những gì tôi đang tìm kiếm! – thenetimp

1

Query:

select case 
     when total is null then 0 
     else total 
     end as total_with_zeroes, 
     suburb_id 
from (SELECT COUNT(suburb_id) AS total, suburb_id 
     FROM suburbs 
     where suburb_id IN (1,2,3,4) 
    GROUP BY suburb_id) as dt 
+1

Vì không có bản ghi nào có 'suburb_id' là 4, truy vấn bên trong sẽ không trả về NULL cho biểu thức CASE để nắm bắt. –

4

này:

SELECT id, COUNT(suburb_id) 
FROM (
     SELECT 1 AS id 
     UNION ALL 
     SELECT 2 AS id 
     UNION ALL 
     SELECT 3 AS id 
     UNION ALL 
     SELECT 4 AS id 
     ) ids 
LEFT JOIN 
     suburbs s 
ON  s.suburb_id = ids.id 
GROUP BY 
     id 

hoặc điều này:

SELECT id, 
     (
     SELECT COUNT(*) 
     FROM suburb 
     WHERE suburb_id = id 
     ) 
FROM (
     SELECT 1 AS id 
     UNION ALL 
     SELECT 2 AS id 
     UNION ALL 
     SELECT 3 AS id 
     UNION ALL 
     SELECT 4 AS id 
     ) ids 

Bài viết này so sánh hiệu suất của hai phương pháp:

, mặc dù nó không quan trọng nhiều trong trường hợp của bạn, như bạn đang truy vấn chỉ 4 hồ sơ.

+0

Puke. Nhưng đúng. Mysql có rất nhiều tính năng funky "không chuẩn", làm sao nó không có bộ tạo chuỗi? btw, ít nhất một số mã ngắn gọn, bạn có thể xóa 'ALL' khỏi' UNION 'của bạn (tất cả các giá trị là duy nhất và đã được sắp xếp, do đó kết quả sẽ giống với' UNION') và loại bỏ tất cả trừ giá trị đầu tiên 'AS ID'. Và bạn có thể in-line nó: 'FROM (SELECT 1 AS id UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) ids'. – Bohemian

1

Giải pháp @ geofftnz hoạt động tốt nếu tất cả các điều kiện đơn giản như trong trường hợp này. Nhưng tôi chỉ phải giải quyết một vấn đề tương tự để tạo báo cáo trong đó mỗi cột trong báo cáo là một truy vấn khác. Khi bạn cần kết hợp các kết quả từ một số câu lệnh chọn, sau đó một cái gì đó như thế này có thể làm việc.

Bạn có thể phải tạo lập trình truy vấn này theo chương trình. Sử dụng các phép nối trái cho phép truy vấn trả về các hàng ngay cả khi không có kết quả phù hợp với suburb_id với một id đã cho. Nếu db của bạn hỗ trợ nó (mà hầu hết), bạn có thể sử dụng IFNULL để thay thế null với 0:

select IFNULL(a.count,0), IFNULL(b.count,0), IFNULL(c.count,0), IFNULL(d.count,0) 
from (select count(suburb_id) as count from suburbs where id=1 group by suburb_id) a, 
left join (select count(suburb_id) as count from suburbs where id=2 group by suburb_id) b on a.suburb_id=b.suburb_id 
left join (select count(suburb_id) as count from suburbs where id=3 group by suburb_id) c on a.suburb_id=c.suburb_id 
left join (select count(suburb_id) as count from suburbs where id=4 group by suburb_id) d on a.suburb_id=d.suburb_id; 

Những điều tốt đẹp về việc này là (nếu cần thiết) mỗi "trái tham gia" có thể sử dụng hơi khác nhau (có thể khá phức tạp) truy vấn.

Disclaimer: cho tập dữ liệu lớn, loại truy vấn có thể không thực hiện rất tốt (tôi không viết đủ sql để biết mà không điều tra thêm), nhưng ít nhất nó sẽ cho kết quả hữu ích ;-)