postgresql pivot crosstab postgresql-9.3

Consulta dinámica dinámica usando PostgreSQL 9.3



pivot crosstab (2)

Si bien es un proceso de dos pasos, este método creará un pivote con columnas dinámicas, sin la necesidad de especificar el conjunto de resultados y sin crear tablas temporales.

Primero definimos una función que crea una declaración preparada dinámicamente:

CREATE OR REPLACE FUNCTION flowms.pivotcode_sql( tablename character varying, rowc character varying, colc character varying, cellc character varying, celldatatype character varying) RETURNS character varying LANGUAGE ''plpgsql'' COST 100 VOLATILE AS $BODY$ declare dynsql1 varchar; dynsql2 varchar; columnlist varchar; begin -- 1. retrieve list of column names. dynsql1 = ''select string_agg(distinct ''''"''''||''||colc||''||''''" ''||celldatatype||'''''','''','''' order by ''''"''''||''||colc||''||''''" ''||celldatatype||'''''') from ''||tablename||'';''; execute dynsql1 into columnlist; -- 2. set up the crosstab query --tablename = REPLACE(text, '''''', E''//"'') dynsql2 = ''prepare crosstab_stmt as select * from crosstab ( ''''select ''||rowc||'',''||colc||'',''||cellc||'' from ''||replace(tablename, chr(39),E''/'/''')||'' group by 1,2 order by 1,2'''', ''''select distinct ''||colc||'' from ''||replace(tablename, chr(39),E''/'/''')||'' order by 1'''' ) as newtable ( ''||rowc||'' varchar,''||columnlist||'' );''; deallocate all; execute dynsql2; return dynsql2; end $BODY$;

Ahora puedes llamar a la función

select pivotcode_sql(''tablename'', ''rowfield'', ''columnfield'', ''sum(value)'', ''integer'');

que creará la declaración preparada. A continuación, puede ejecutar la declaración preparada:

execute crosstab_stmt;

Tengo una tabla llamada como Product :

create table product ( ProductNumber varchar(10), ProductName varchar(10), SalesQuantity int, Salescountry varchar(10) );

Valores de muestra:

insert into product values (''P1'', ''PenDrive'', 50, ''US'') , (''P2'', ''Mouse'', 100, ''UK'') , (''P3'', ''KeyBoard'', 250, ''US'') , (''P1'', ''PenDrive'', 300, ''US'') , (''P2'', ''Mouse'', 450, ''UK'') , (''P5'', ''Dvd'', 50, ''UAE'');

Quiero generar Salescountry''s nombres Salescountry''s y mostrar la suma de las SalesQuantity de SalesQuantity en ese país.

Resultado Esperado:

ProductName US UK UAE ---------------------------- PenDrive 350 0 0 Mouse 0 550 0 KeyBoard 250 0 0 Dvd 0 0 50

Lo hice usando SQL Server 2008 R2 :

DECLARE @cols AS NVARCHAR(MAX), @query AS NVARCHAR(MAX); SET @cols = STUFF((SELECT distinct '','' + QUOTENAME(SalesCountry) FROM Product FOR XML PATH(''''), TYPE ).value(''.'', ''NVARCHAR(MAX)'') ,1,1,'''') set @query = ''SELECT ProductName, '' + @cols + '' from ( select ProductName , SalesQuantity as q , Salescountry from Product ) x pivot ( SUM(q) for Salescountry in ('' + @cols + '') ) p '' PRINT(@query); execute(@query);

¿Cómo lograr esto en Postgres?


SELECT * FROM crosstab ( ''SELECT ProductNumber, ProductName, Salescountry, SalesQuantity FROM product ORDER BY 1'' , $$SELECT unnest(''{US,UK,UAE1}''::varchar[])$$ ) AS ct ( "ProductNumber" varchar , "ProductName" varchar , "US" int , "UK" int , "UAE1" int);

Explicación detallada:

¿ Salescountry completamente dinámica para un número variable de países de Salescountry distintos?