PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Pivô em várias colunas usando Tablefunc


O problema com sua consulta é que b e c compartilhar o mesmo carimbo de data/hora 2012-01-02 00:00:00 , e você tem o timestamp coluna timeof primeiro em sua consulta, então - mesmo que você tenha adicionado ênfase em negrito - b e c são apenas colunas extras que se enquadram no mesmo grupo 2012-01-02 00:00:00 . Apenas o primeiro (b ) é retornado desde (citando o manual):

O row_name coluna deve ser a primeira. A category e value colunas devem ser as duas últimas colunas, nessa ordem. Quaisquer colunas entre row_name e category são tratados como "extras". As colunas "extras" esperam-se que sejam as mesmas para todas as linhas com o mesmo row_name valor.

A ênfase em negrito é minha.
Apenas reverta a ordem das duas primeiras colunas para fazer entity o nome da linha e funciona como desejado:
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 deve ser único, é claro.

Reiterar

  • row_name primeiro
  • (opcional) extra colunas próximo
  • category (conforme definido pelo segundo parâmetro) e value último .

Colunas extras são preenchidas a partir do primeiro linha de cada row_name partição. Os valores de outras linhas são ignorados, há apenas uma coluna por row_name preencher. Normalmente, eles seriam os mesmos para cada linha de um row_name , mas isso é com você.

Para a configuração diferente em sua resposta:

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  -- ??!!

Não é de admirar que as consultas em seu teste tenham um desempenho terrível. Sua configuração de teste tem 14 milhões de linhas e você processa todas deles antes de jogar a maior parte fora com LIMIT 1000 . Para um conjunto de resultados reduzido, adicione as condições WHERE ou um LIMIT à consulta de origem!

Além disso, o array com o qual você trabalha é desnecessariamente caro. Eu gero um nome de linha substituto com denso_rank() em vez disso.

db<>violino aqui - com uma configuração de teste mais simples e menos linhas.