2010-07-14 46 views
12

Tôi đang cố gắng để đếm số lượng người bởi độ tuổi này, và tôi gần như có thể làm điều đó với 2 vấn đề:MySQL GROUP BY độ tuổi bao gồm rỗng dao động

  1. Nếu không có người trong một trao độ tuổi (NULL), khi đó độ tuổi đó không xuất hiện trong kết quả. Ví dụ: trong dữ liệu của tôi không có mục nhập nào cho "Trên 80" để phạm vi ngày không xuất hiện. Về cơ bản, có vẻ như một lỗi trong chương trình khi thiếu các phạm vi ngày.

  2. Tôi muốn đặt hàng kết quả theo một cách cụ thể. Trong truy vấn bên dưới, vì ORDER BY bằng age_range, kết quả cho '20 - 29 'xuất hiện trước kết quả cho' Dưới 20 '.

Dưới đây là một mẫu của các bảng db "thắc mắc":

inquiry_id birth_date 
1   1960-02-01 
2   1962-03-04 
3   1970-03-08 
4   1980-03-02 
5   1990-02-08 

Dưới đây là các truy vấn:

SELECT 
    CASE 
     WHEN age < 20 THEN 'Under 20' 
     WHEN age BETWEEN 20 and 29 THEN '20 - 29' 
     WHEN age BETWEEN 30 and 39 THEN '30 - 39' 
     WHEN age BETWEEN 40 and 49 THEN '40 - 49' 
     WHEN age BETWEEN 50 and 59 THEN '50 - 59' 
     WHEN age BETWEEN 60 and 69 THEN '60 - 69' 
     WHEN age BETWEEN 70 and 79 THEN '70 - 79' 
     WHEN age >= 80 THEN 'Over 80' 
     WHEN age IS NULL THEN 'Not Filled In (NULL)' 
    END as age_range, 
    COUNT(*) AS count 

    FROM (SELECT TIMESTAMPDIFF(YEAR, birth_date, CURDATE()) AS age FROM inquiries) as derived 

    GROUP BY age_range 

    ORDER BY age_range 

Dưới đây là một giải pháp đơn giản dựa trên đề nghị của Wrikken:

SELECT 
    SUM(IF(age < 20,1,0)) as 'Under 20', 
    SUM(IF(age BETWEEN 20 and 29,1,0)) as '20 - 29', 
    SUM(IF(age BETWEEN 30 and 39,1,0)) as '30 - 39', 
    SUM(IF(age BETWEEN 40 and 49,1,0)) as '40 - 49', 
    SUM(IF(age BETWEEN 50 and 59,1,0)) as '50 - 59', 
    SUM(IF(age BETWEEN 60 and 69,1,0)) as '60 - 69', 
    SUM(IF(age BETWEEN 70 and 79,1,0)) as '70 - 79', 
    SUM(IF(age >=80, 1, 0)) as 'Over 80', 
    SUM(IF(age IS NULL, 1, 0)) as 'Not Filled In (NULL)' 

FROM (SELECT TIMESTAMPDIFF(YEAR, birth_date, CURDATE()) AS age FROM inquiries) as derived 
+0

Câu hỏi của bạn đã trả lời câu hỏi của riêng tôi. Cảm ơn vì điều đó :) –

Trả lời

10

một thay thế cho bảng phạm vi (trong đó có sở thích của tôi), một câu trả lời đơn hàng có thể là:

SELECT 
    SUM(IF(age < 20,1,0)) as 'Under 20', 
    SUM(IF(age BETWEEN 20 and 29,1,0)) as '20 - 29', 
    SUM(IF(age BETWEEN 30 and 39,1,0)) as '30 - 39', 
    SUM(IF(age BETWEEN 40 and 49,1,0)) as '40 - 49', 
...etc. 
FROM inquiries; 
+0

Tôi vừa thử sử dụng phương pháp SUM, và nó đơn giản và hoạt động hoàn hảo. Nó đặt SUMs theo thứ tự được chỉ định. Tôi đã đặt giải pháp cuối cùng trong câu hỏi ban đầu trong trường hợp ai đó muốn xem nó. – Mitchell

1
  1. Tạo một bảng có chứa tất cả các phạm vi và sử dụng phép nối ngoài.
  2. Sắp xếp theo giá trị số trong một cột của bảng mà

    CHỌN phạm vi, .... TỪ dãy LEFT JOIN (subquery của bạn) ON (ranges.range = your_range) ... ORDER BY range.year ASC

+0

Điều này có vẻ là một giải pháp mà sẽ chăm sóc cả hai vấn đề ban đầu của tôi, tuy nhiên tôi đang gặp khó khăn trong việc tìm ra mệnh đề JOIN. Trong giải pháp trên, "your_range" sẽ là gì? – Mitchell

2

Một cách để sắp xếp kết quả sẽ giới thiệu một cột trong câu lệnh chọn và cho nó giá trị xếp hạng theo cách bạn muốn kết quả được sắp xếp với phần còn lại và sau đó đặt hàng theo hàng đó, ví dụ

SELECT 
CASE 
    WHEN age < 20 THEN 'Under 20' 
    WHEN age BETWEEN 20 and 29 THEN '20 - 29' 
    WHEN age BETWEEN 30 and 39 THEN '30 - 39' 
    WHEN age BETWEEN 40 and 49 THEN '40 - 49' 
    WHEN age BETWEEN 50 and 59 THEN '50 - 59' 
    WHEN age BETWEEN 60 and 69 THEN '60 - 69' 
    WHEN age BETWEEN 70 and 79 THEN '70 - 79' 
    WHEN age >= 80 THEN 'Over 80' 
    WHEN age IS NULL THEN 'Not Filled In (NULL)' 
END as age_range, 
COUNT(*) AS count, 
CASE 
    WHEN age < 20 THEN 1 
    WHEN age BETWEEN 20 and 29 THEN 2 
    WHEN age BETWEEN 30 and 39 THEN 3 
    WHEN age BETWEEN 40 and 49 THEN 4 
    WHEN age BETWEEN 50 and 59 THEN 5 
    WHEN age BETWEEN 60 and 69 THEN 6 
    WHEN age BETWEEN 70 and 79 THEN 7 
    WHEN age >= 80 THEN 8 
    WHEN age IS NULL THEN 9 
END as ordinal 

FROM (SELECT TIMESTAMPDIFF(YEAR, birth_date, CURDATE()) AS age FROM inquiries) as derived 

GROUP BY age_range 

ORDER BY ordinal