sql >> Databasteknik >  >> RDS >> PostgreSQL

Postgres - hur returnerar man rader med 0 antal för saknade data?

Rätt lösning

SELECT *
FROM  (
   SELECT day::date
   FROM   generate_series(timestamp '2007-12-01'
                        , timestamp '2008-12-01'
                        , interval  '1 month') day
   ) d
LEFT   JOIN (
   SELECT date_trunc('month', date_col)::date AS day
        , count(*) AS some_count
   FROM   tbl
   WHERE  date_col >= date '2007-12-01'
   AND    date_col <= date '2008-12-06'
-- AND    ... more conditions
   GROUP  BY 1
   ) t USING (day)
ORDER  BY day;
  • Använd LEFT JOIN , naturligtvis.

  • generate_series() kan producera en tabell med tidsstämplar i farten, och mycket snabbt.

  • Det går i allmänhet snabbare att samla före du går med. Jag gav nyligen ett testfall på sqlfiddle.com i detta relaterade svar:

    • PostgreSQL - ordna efter en array
  • Kasta timestamp till date (::date ) för ett grundläggande format. För mer använd to_char() .

  • GROUP BY 1 är syntaxstenografi för att referera till den första utdatakolumnen. Kan vara GROUP BY day också, men det kan komma i konflikt med en befintlig kolumn med samma namn. Eller GROUP BY date_trunc('month', date_col)::date men det är för långt för min smak.

  • Fungerar med tillgängliga intervallargument för date_trunc() .

  • count() producerar aldrig NULL (0 för inga rader), men LEFT JOIN gör.
    För att returnera 0 istället för NULL i den yttre SELECT , använd COALESCE(some_count, 0) AS some_count . Manualen.

  • För en mer generisk lösning eller godtyckliga tidsintervall överväg detta närbesläktade svar:

    • Bästa sättet att räkna poster efter godtyckliga tidsintervall i Rails+Postgres


  1. SQL CREATE TABLE … SOM SELECT-sats

  2. BIN_TO_NUM() Funktion i Oracle

  3. Dynamisk SQL (EXECUTE) som villkor för IF-satsen

  4. Ansluter till Lotus Notes från Java