2013-07-29 10 views
6

Ho scritto una query per ottenere record di mese-saggio nella tabella utente nel modo seguenteMysql per selezionare record di mese-saggio, anche se non esistono dati

SELECT COUNT(`userID`) AS total, DATE_FORMAT(`userRegistredDate` , '%b') AS 
MONTH , YEAR(`userRegistredDate`) AS year 
FROM `users` 
GROUP BY DATE_FORMAT(FROM_UNIXTIME(`userRegistredDate` , '%b')) 

uscita:

total  MONTH year 
--------------------------- 
3   May  2013 
2   Jul  2013 
-------------------------- 

Output previsto:

total  MONTH year 
--------------------------- 
0   Jan  2013 
0   Feb  2013 
0   Mar  2013 
0   Apr  2013 
3   May  2013 
0   Jun  2013 
2   Jul  2013 
-------------------------- 

Ho bisogno di mostrare il record anche se i dati non esistono. Come fare questo?

+0

In sostanza si vuole mesi inesistenti (inesistente come in non si dispone di un record per quel mese/anno) di presentarsi quando non si dispone di un record con esso ? – Prix

+0

@Prix esattamente, anche se non c'è nessun record per un mese specifico –

risposta

12

Non voglio dire molto su efficienza, non ho ancora testato contro altri metodi, ma senza avere una tabella temporanea questo sembra un modo giusto per andare.

SELECT COUNT(u.userID) AS total, m.month 
    FROM (
      SELECT 'Jan' AS MONTH 
      UNION SELECT 'Feb' AS MONTH 
      UNION SELECT 'Mar' AS MONTH 
      UNION SELECT 'Apr' AS MONTH 
      UNION SELECT 'May' AS MONTH 
      UNION SELECT 'Jun' AS MONTH 
      UNION SELECT 'Jul' AS MONTH 
      UNION SELECT 'Aug' AS MONTH 
      UNION SELECT 'Sep' AS MONTH 
      UNION SELECT 'Oct' AS MONTH 
      UNION SELECT 'Nov' AS MONTH 
      UNION SELECT 'Dec' AS MONTH 
     ) AS m 
LEFT JOIN users u 
ON MONTH(STR_TO_DATE(CONCAT(m.month, ' 2013'),'%M %Y')) = MONTH(u.userRegistredDate) 
    AND YEAR(u.userRegistredDate) = '2013' 
GROUP BY m.month 
ORDER BY 1+1; 

Se si effettua l'unione in base a un formato di data si può anche ridurre il lavoro e il carico sulla query.

SELECT COUNT(u.userID) AS total, DATE_FORMAT(merge_date,'%b') AS month, YEAR(m.merge_date) AS year 
    FROM (
      SELECT '2013-01-01' AS merge_date 
      UNION SELECT '2013-02-01' AS merge_date 
      UNION SELECT '2013-03-01' AS merge_date 
      UNION SELECT '2013-04-01' AS merge_date 
      UNION SELECT '2013-05-01' AS merge_date 
      UNION SELECT '2013-06-01' AS merge_date 
      UNION SELECT '2013-07-01' AS merge_date 
      UNION SELECT '2013-08-01' AS merge_date 
      UNION SELECT '2013-09-01' AS merge_date 
      UNION SELECT '2013-10-01' AS merge_date 
      UNION SELECT '2013-11-01' AS merge_date 
      UNION SELECT '2013-12-01' AS merge_date 
     ) AS m 
LEFT JOIN users u 
     ON MONTH(m.merge_date) = MONTH(u.userRegistredDate) 
      AND YEAR(m.merge_date) = YEAR(u.userRegistredDate) 
GROUP BY m.merge_date 
ORDER BY 1+1; 

Live DEMO of both queries.

2

Potrebbe essere necessario un tavolo per tenere ogni record di "mese". Una tabella temporanea può fare il trucco:

drop table if extists temp_months; 
create temporary table temp_months 
    month date, 
    index idx_date(month); 
insert into temp_months 
    values ('2013-01-31'), ('2013-02-28'), ... 

E ora, è possibile LEFT JOIN i dati con questa tabella temporanea appena creata:

SELECT 
    COUNT(`userID`) AS total, 
    DATE_FORMAT(m.month , '%b') AS 
    MONTH , 
    YEAR(m.month) AS year 
FROM 
    months as m 
    left join `users` as u on m.month = last_day(FROM_UNIXTIME(`userRegistredDate`, '%b') 
GROUP BY 
    last_day(m.month); 

Si noti che si può mettere la creazione tabella temporanea (e riempire) in una stored procedure.

Io uso last_day per semplicità, ma sei libero di utilizzare qualsiasi data nel mese che ti piace, se ti unisci correttamente.

Spero che questo aiuti

+0

Non è una cattiva idea, ma penso che un semplice sindacato con mesi dovrebbe essere meno costoso. – Prix

+0

@Prix Se l'utente ha solo bisogno di farlo per alcuni mesi, sono assolutamente d'accordo con te. Ma se l'utente ha bisogno di affrontare un sacco di mesi (o anni), tale approccio sarebbe soggetto a errori. Inoltre, una tabella temporanea può essere creata e riempita con una stored procedure, e può essere riutilizzata tutte le volte che l'utente ha bisogno. – Barranka

Problemi correlati