sql >> Databáze >  >> RDS >> PostgreSQL

Postgres - jak vrátit řádky s počtem 0 pro chybějící data?

Správné řešení

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;
  • Použijte LEFT JOIN , samozřejmě.

  • generate_series() dokáže vytvořit tabulku časových razítek za běhu a velmi rychle.

  • Obecně je rychlejší agregovat před přidáš se. Nedávno jsem poskytl testovací případ na sqlfiddle.com v této související odpovědi:

    • PostgreSQL – řazení podle pole
  • Odešlete timestamp do date (::date ) pro základní formát. Pro více použijte to_char() .

  • GROUP BY 1 je zkratka syntaxe odkazující na první výstupní sloupec. Může to být GROUP BY day také, ale to může být v konfliktu s existujícím sloupcem se stejným názvem. Nebo GROUP BY date_trunc('month', date_col)::date ale to je na můj vkus příliš dlouhé.

  • Pracuje s dostupnými argumenty intervalu pro date_trunc() .

  • count() nikdy nevytváří NULL (0 pro žádné řádky), ale LEFT JOIN ano.
    Vrátí 0 místo NULL ve vnějším SELECT , použijte COALESCE(some_count, 0) AS some_count . Manuál.

  • Pro obecnější řešení nebo libovolné časové intervaly zvažte tuto úzce související odpověď:

    • Nejlepší způsob, jak počítat záznamy podle libovolných časových intervalů v Rails+Postgres


  1. SQL (ORACLE):ORDER BY a LIMIT

  2. Odebrat SCHEMABINDING z funkce definované uživatelem na serveru SQL Server

  3. Jak mohu číst data ze šifrované databáze pomocí SQLiteAssetHelper?

  4. Automatické zvýšení na částečném primárním klíči s Entity Framework Core