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

Dotazování na počty řádků oddělené podle období

crosstab() funkce se dvěma parametry.

Mělo by to fungovat takto, abyste získali hodnoty pro rok 2012:

SELECT * FROM crosstab(
     $$SELECT testname, to_char(last_update, 'mon_YYYY'), count(*)::int AS ct
        FROM   tests
        WHERE  current_status = 'FAILED'
        AND    last_update >= '2012-01-01 0:0'
        AND    last_update <  '2013-01-01 0:0'  -- proper date range!
        GROUP  BY 1,2
        ORDER  BY 1,2$$

    ,$$VALUES
      ('jan_2012'::text), ('feb_2012'), ('mar_2012')
    , ('apr_2012'), ('may_2012'), ('jun_2012')
    , ('jul_2012'), ('aug_2012'), ('sep_2012')
    , ('oct_2012'), ('nov_2012'), ('dec_2012')$$)
AS ct (testname  text
   , jan_2012 int, feb_2012 int, mar_2012 int
   , apr_2012 int, may_2012 int, jun_2012 int
   , jul_2012 int, aug_2012 int, sep_2012 int
   , oct_2012 int, nov_2012 int, dec_2012 int);

Podrobné vysvětlení naleznete v této související otázce.

Netestoval jsem. Jak poznamenal @Craig, vzorové hodnoty by pomohly.
Nyní testováno s mým vlastním testovacím případem.

Nezobrazovat hodnoty NULL

Hlavní problém (že by se měsíce bez řádků vůbec nezobrazovaly) je odvrácen pomocí crosstab() funkce se dvěma parametry.

Nemůžete použít COALESCE ve vnitřním dotazu, protože NULL hodnoty jsou vloženy pomocí crosstab() sám. Můžete ...

1. Zabalte celou věc do poddotazu:

SELECT testname
      ,COALESCE(jan_2012, 0) AS jan_2012
      ,COALESCE(feb_2012, 0) AS feb_2012
      ,COALESCE(mar_2012, 0) AS mar_2012
      , ...
FROM (
    -- query from above)
    ) x;

2. LEFT JOIN primární dotaz na úplný seznam měsíců.

V tomto případě druhý parametr z definice nepotřebujete.
Pro větší rozsah můžete použít generate_series() k vytvoření hodnot.

SELECT * FROM crosstab(
     $$SELECT t.testname, m.mon, count(x.testname)::int AS ct
       FROM  (
          VALUES
           ('jan_2012'::text), ('feb_2012'), ('mar_2012')
          ,('apr_2012'), ('may_2012'), ('jun_2012')
          ,('jul_2012'), ('aug_2012'), ('sep_2012')
          ,('oct_2012'), ('nov_2012'), ('dec_2012')
       ) m(mon)
       CROSS JOIN (SELECT DISTINCT testname FROM tests) t
       LEFT JOIN (
          SELECT testname
                ,to_char(last_update, 'mon_YYYY') AS mon
          FROM   tests
          WHERE  current_status = 'FAILED'
          AND    last_update >= '2012-01-01 0:0'
          AND    last_update <  '2013-01-01 0:0'  -- proper date range!
          ) x USING (mon)
       GROUP  BY 1,2
       ORDER  BY 1,2$$
     )
AS ct (testname  text
   , jan_2012 int, feb_2012 int, mar_2012 int
   , apr_2012 int, may_2012 int, jun_2012 int
   , jul_2012 int, aug_2012 int, sep_2012 int
   , oct_2012 int, nov_2012 int, dec_2012 int);

Testovací případ s ukázkovými daty

Zde je testovací případ s některými ukázkovými daty, které OP neposkytlo. Použil jsem to, abych to otestoval a zprovoznil.

CREATE TEMP TABLE tests (
  id             bigserial PRIMARY KEY
 ,testname       text NOT NULL
 ,last_update    timestamp without time zone NOT NULL DEFAULT now()
 ,current_status text NOT NULL
 );

INSERT INTO tests (testname, last_update, current_status)
VALUES
  ('foo', '2012-12-05 21:01', 'FAILED')
 ,('foo', '2012-12-05 21:01', 'FAILED')
 ,('foo', '2012-11-05 21:01', 'FAILED')
 ,('bar', '2012-02-05 21:01', 'FAILED')
 ,('bar', '2012-02-05 21:01', 'FAILED')
 ,('bar', '2012-03-05 21:01', 'FAILED')
 ,('bar', '2012-04-05 21:01', 'FAILED')
 ,('bar', '2012-05-05 21:01', 'FAILED');



  1. Jak aktualizovat sloupec datového typu JSON v MySQL 5.7.10?

  2. Použití SQLAlchemy ORM pro neprimární klíč, jedinečné, automaticky se zvyšující ID

  3. Jak zřetězit text z více řádků do jednoho textového řetězce na serveru SQL Server

  4. Jak získat Mysql rownum nepřetržitě přes stránkování