PostgreSQL: как преобразовать «PIVOT» из T-SQL в процедуру PLPGSQL

#postgresql #stored-procedures #pivot #plpgsql

#postgresql #хранимые процедуры #сводная #plpgsql

Вопрос:

Я хотел бы преобразовать хранимую процедуру из T-SQL в PL / PGSQL. Вот код T-SQL

 SELECT NO_PTF, coalesce(1, 0) as RISK_1, coalesce(2, 0) as RISK_2, coalesce(3, 0) as RISK_3, coalesce(4, 0) as RISK_4
    FROM (
            SELECT D.NO_PTF, C.NB_DEG_RSQ, D.MT_DEM/100 as MT_DEM
                FROM public.TB_Demande      D
                    INNER JOIN
                    public.TB_Compartiment C ON D.ID_CPA = C.ID_CPA
                                                AND D.MC_UTL = 'F3000'
                                                AND C.IN_ACT = true
            ) Q
    PIVOT (SUM(Q.MT_DEM) FOR Q.NB_DEG_RSQ IN (1, 2, 3, 4)) as PVT
    )
  

Я попытался заменить PIVOT перекрестной таблицей. Но у меня ошибка. Вот мой код PL / PGSQL

 SELECT NO_PTF, coalesce(1, 0) as RISK_1, coalesce(2, 0) as RISK_2, coalesce(3, 0) as RISK_3, coalesce(4, 0) as RISK_4
    FROM (
            SELECT D.NO_PTF, C.NB_DEG_RSQ, D.MT_DEM/100 as MT_DEM
                FROM public.TB_Demande      D
                    INNER JOIN
                    public.TB_Compartiment C ON D.ID_CPA = C.ID_CPA
                                                AND D.MC_UTL = 'F3000'
                                                AND C.IN_ACT = true
            ) Q
    crosstab (SUM(Q.MT_DEM) FOR Q.NB_DEG_RSQ IN (1, 2, 3, 4)) as PVT
  

У кого-нибудь есть идея о правильном способе использования перекрестной таблицы здесь?

Комментарии:

1. coalesce(1, 0) не имеет смысла. Это то же самое, что 1

2. да, он всегда возвращает 1. Но мой вопрос касается преобразования сводной таблицы в перекрестную таблицу или любого другого решения. У вас есть идея?

Ответ №1:

Я не совсем уверен, что понимаю синтаксис PIVOT, но обычно это намного проще в Postgres с использованием фильтрованной агрегации, а не несколько неуклюжей crosstab() функции.

Я думаю, это должно быть эквивалентно:

 select no_ptf,  
       sum(mt_dem) filter (where NB_DEG_RSQ = 1) as risk_1,
       sum(mt_dem) filter (where NB_DEG_RSQ = 2) as risk_2,
       sum(mt_dem) filter (where NB_DEG_RSQ = 3) as risk_3,
       sum(mt_dem) filter (where NB_DEG_RSQ = 4) as risk_4
from (       
  SELECT D.NO_PTF, C.NB_DEG_RSQ, D.MT_DEM/100 as MT_DEM
  FROM public.TB_Demande      D
    INNER JOIN public.TB_Compartiment C 
       ON D.ID_CPA = C.ID_CPA
      AND D.MC_UTL = 'F3000'
      AND C.IN_ACT = true
)      
GROUP BY no_ptf;
  

Комментарии:

1. Даже в SQL Server возможна и часто предпочтительнее фильтрованная агрегация по сравнению с PIVOT. Объем кода в обоих случаях одинаков, но я уверен, что никто не может вспомнить, как написать сводную, не проверив документы. Я подозреваю, что сначала был создан UNPIVOT (действительно полезная команда), затем кто-то сказал: «Это было слишком просто, почему бы не добавить PIVOT?»