sql >> Databasteknik >  >> RDS >> PostgreSQL

Pivotera på flera kolumner med Tablefunc

Problemet med din fråga är att b och c dela samma tidsstämpel 2012-01-02 00:00:00 , och du har timestamp kolumn timeof först i din fråga, så - även om du lagt till fet betoning - b och c är bara extra kolumner som faller i samma grupp 2012-01-02 00:00:00 . Endast den första (b ) returneras sedan (med hänvisning till manualen):

row_name kolumnen måste vara först. category och value kolumner måste vara de två sista kolumnerna, i den ordningen. Alla kolumner mellan row_name och category behandlas som "extra". De "extra" kolumnerna förväntas vara desamma för alla rader med samma row_name värde.

Fet betoning min.
Återställ bara ordningen på de två första kolumnerna för att skapa entity radnamnet och det fungerar som önskat:

SELECT * FROM crosstab(
      'SELECT entity, timeof, status, ct
       FROM   t4
       ORDER  BY 1'
      ,'VALUES (1), (0)')
 AS ct (
    "Attribute" character
   ,"Section" timestamp
   ,"status_1" int
   ,"status_0" int);

entity måste naturligtvis vara unikt.

Upprepa

  • row_name först
  • (valfritt) extra kolumner nästa
  • category (enligt definitionen av den andra parametern) och value sista .

Extra kolumner fylls från den första rad från varje row_name dela. Värden från andra rader ignoreras, det finns bara en kolumn per row_name att fylla. Vanligtvis skulle de vara desamma för varje rad i en row_name , men det är upp till dig.

För de olika inställningarna i ditt svar:

SELECT localt, entity
     , msrmnt01, msrmnt02, msrmnt03, msrmnt04, msrmnt05  -- , more?
FROM   crosstab(
        'SELECT dense_rank() OVER (ORDER BY localt, entity)::int AS row_name
              , localt, entity -- additional columns
              , msrmnt, val
         FROM   test
         -- WHERE  ???   -- instead of LIMIT at the end
         ORDER  BY localt, entity, msrmnt
         -- LIMIT ???'   -- instead of LIMIT at the end
     , $$SELECT generate_series(1,5)$$)  -- more?
     AS ct (row_name int, localt timestamp, entity int
          , msrmnt01 float8, msrmnt02 float8, msrmnt03 float8, msrmnt04 float8, msrmnt05 float8 -- , more?
            )
LIMIT 1000  -- ??!!

Inte konstigt att frågorna i ditt test fungerar fruktansvärt. Din testkonfiguration har 14 miljoner rader och du bearbetar alla av dem innan du kastar bort det mesta med LIMIT 1000 . För en reducerad resultatuppsättning lägg till WHERE-villkor eller en LIMIT till källfrågan!

Dessutom är arrayen du arbetar med onödigt dyr. Jag genererar ett surrogatradnamn med dense_rank() istället.

db<>fiol här - med en enklare testinställning och färre rader.



  1. mysql_num_rows() förväntar sig att parameter 1 är resurs, boolean ges in

  2. Huvudkonceptet för SQL Server-låsning

  3. Proaktiva SQL Server Health Checks, Del 3:Inställningar för instans och databas

  4. Hur man skapar ordningsnummer i PostgreSQL