Search Postgresql Archives

Re: Unpivot / uncrosstab support?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



> -----Original Message-----
> From: pgsql-general-owner@xxxxxxxxxxxxxx [mailto:pgsql-general-owner@xxxxxxxxxxxxxx] On Behalf Of Josh.Vote@xxxxxxxx
> Sent: Thursday, 13 May 2010 10:41 AM
> To: pgsql-general@xxxxxxxxxxxxxx
> Subject: [ExternalEmail]  Unpivot / uncrosstab support?
> 
> Hi,
> 
> I was wondering if Postgresql (8.3 or later) had an equivalent function to the MS-SQL function "unpivot"? I've spotted the user contributed crosstab which is similar to the "pivot" function, but I can't find an equivalent "uncrosstab".
> 
> Essentially what I'm trying to do is take a table like this...
> 
> clientID    clientName           contact1    contact2    contact3    contact4
> ----------- -------------------- ----------- ----------- ----------- -----------
> 1           ABC Corp             1           34          2           NULL
> 2           DEF Foundation       6           2           8           9
> 3           GHI Inc.             5           9           NULL        NULL
> 4           XYZ Industries       24          NULL        6           NULL
> 
> ...and get a result like this...
>
> clientID    ContactNumber           ContactID
> ----------- ----------------------- -----------
> 1           contact1                1
> 1           contact2                34
> 1           contact3                2
> 2           contact1                6
> 2           contact2                2
> 2           contact3                8
> 2           contact4                9
> 3           contact1                5
> 3           contact2                9
> 4           contact1                24
> 4           contact3                6
>
> Which can be accomplished with unpivot.
>
> For more info I've stolen the example from http://weblogs.sqlteam.com/jeffs/archive/2008/04/23/unpivot.aspx
>
> Thanks
> Josh Vote

Well after doing some of my own investigating I came up with my own solution, it's slow, unoptimised and specific to my solution but it works. Currently this gets dumped into a materialized view so the performance isn't a huge problem for me. 

The example given is making the assumption that you are unpivoting from ONLY columns which are double precision and that your unpivoting column names are fixed. It should be easy enough to change these assumptions to your own needs...

-- This function sucks, it's hardcoded to only extract double precision columns but it should be easy enough to change. It also has pretty poor performance.
CREATE OR REPLACE FUNCTION get_column_value(text, text, text, text)
  RETURNS double precision AS
$BODY$
	DECLARE
		val double precision := null;
		rRec  RECORD; 
	BEGIN
		FOR rRec IN EXECUTE('SELECT ' || quote_ident($1) || ' AS val FROM ' || quote_ident($2) || ' WHERE ' || quote_ident($3) || ' = ' || quote_literal($4)) LOOP
			val = rRec.val;
		END LOOP;
		
		RETURN val;
	END;
$BODY$
  LANGUAGE 'plpgsql';


-- This is the actual query, it cross joins the list of column names against the actual table and includes the actual column values too.
SELECT * 
FROM
	(SELECT my_table.clientid, my_columns.column_name as contact_number, get_column_value(my_columns.column_name, 'clients_table', 'clientid', my_table.clientid) AS contactid
	FROM clients_table my_table
	CROSS JOIN
		(SELECT a.attnum, a.attname AS column_name
		FROM pg_class c, pg_attribute a, pg_type t
		WHERE c.relname = clients_table ' 
			AND a.attnum > 0 
			AND a.attrelid = c.oid 
			AND a.atttypid = t.oid 
			AND (a.attname = 'contact1'
				OR a.attname = 'contact2'
				OR a.attname = 'contact3',
				OR a.attname = 'contact4')) my_columns) joined_table
WHERE contactid IS NOT NULL;

Running the query generates the normalized unpivot table. 

Hope someone else finds this useful...

Josh Vote

-- 
Sent via pgsql-general mailing list (pgsql-general@xxxxxxxxxxxxxx)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-general


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Postgresql Jobs]     [Postgresql Admin]     [Postgresql Performance]     [Linux Clusters]     [PHP Home]     [PHP on Windows]     [Kernel Newbies]     [PHP Classes]     [PHP Books]     [PHP Databases]     [Postgresql & PHP]     [Yosemite]
  Powered by Linux