2010-07-14 10 views
12

sto cercando di contare il numero di persone per fasce di età, e ho quasi può farlo con 2 problemi:GROUP BY MySQL fascia di età compresa nulla va

  1. Se non ci sono persone in un dato fascia di età (NULL), quindi la fascia di età non appare nei risultati. Ad esempio, nei miei dati non ci sono voci per "Oltre 80", quindi l'intervallo di date non viene visualizzato. Fondamentalmente, sembra un errore nella programmazione quando mancano intervalli di date.

  2. Desidero ordinare i risultati in un modo specifico. Nella query seguente, poiché ORDER BY è per age_range, i risultati per "20 - 29" precedono i risultati per "Under 20".

Ecco un esempio della tabella db "inchieste":

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

Ecco la domanda:

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 

Ecco una soluzione semplice basata sul suggerimento di 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

La tua domanda ha già risposto alla mia stessa domanda. Grazie per quello :) –

risposta

10

un'alternativa alla tabella gamma (che ha la mia preferenza), una risposta sola riga potrebbe essere:

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

Ho appena provato ad utilizzare l'approccio SUM, ed è semplice e funziona perfettamente. Mette le SUM nell'ordine specificato. Ho messo la soluzione finale nella domanda originale nel caso qualcuno volesse vederla. – Mitchell

1
  1. Creare una tabella che contenga tutti gli intervalli e utilizzare join esterno.
  2. Ordina per valore numerico in un'altra colonna della tabella

    gamma selezionata, .... DA gamme LEFT JOIN (Il tuo subquery) il (ranges.range = your_range) ... ORDER BY range.year ASC

+0

Questa sembra essere una soluzione che si prenderà cura di entrambi i miei problemi iniziali, tuttavia ho difficoltà a capire la clausola JOIN. Nella soluzione sopra, cosa sarebbe "your_range"? – Mitchell

2

Un modo di ordinare i risultati sarebbero stati l'introduzione di una colonna nella dichiarazione prescelta e dandogli un valore di rango del modo in cui si desidera che i risultati da ordinare con il resto e poi ordinare da quella riga, ad esempio

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