Reputation: 33581
I have a query that goes has columns like this...
systemid | created | updated
for each system id there is an arbitrary set of name value pairs in a table that looks like this.
systemid | name | value
so this table might have
1,'name','ben'
1,'age',42
2,'name','john'
2,'age',22
2,'favoritecolor','red'
Does anybody know of a way to make a query return all name value pairs for a systemid as a name/value pair type? I'd like to get a result like this.
systemid | created | updated | profiledata
1,'name','ben','jan 1, 2012, 'name=>\'ben\',age=42'
2,'name','john','sept 15, 2011, 'name=>\'john\',age=22, favoritecolor=>\'red\''
Upvotes: 0
Views: 1136
Reputation: 154695
Any solution to this is roughly going to have one of the following forms:
SELECT table1.systemid,
created,
updated,
some_aggregate_function(name, value) AS profiledata
FROM table1 JOIN table2 ON table1.systemid = table2.systemid
GROUP BY table1.systemid, created, updated
or
SELECT table1.systemid,
created,
updated,
some_aggregate_function(some_function(name, value)) AS profiledata
FROM table1 JOIN table2 ON table1.systemid = table2.systemid
GROUP BY table1.systemid, created, updated
Here is a fairly hacky, ugly example of the second approach, which returns as the fourth column a JSON object with name/value pairs:
SELECT table1.systemid,
created,
updated,
'{' || array_to_string(
array_agg(
'"' || name || '":"' || value || '"'
), ','
) || '}' AS profiledata
FROM table1
JOIN table2
ON table1.systemid = table2.systemid
GROUP BY table1.systemid, created, updated;
If you want something prettier to achieve the same result, you might want to look into defining your own aggregate functions. I'm afraid I'm not any kind of SQL whiz so I can't come up with a nice, elegant solution off the top of my head, but hopefully this puts you on the right track.
Upvotes: 0
Reputation: 9150
I guess you could try something along these lines:
postgres=# CREATE TABLE attr(systemid int, name varchar(32), value varchar(64));
CREATE TABLE
postgres=#
postgres=# INSERT INTO attr VALUES(1,'name','ben');
INSERT 0 1
postgres=# INSERT INTO attr VALUES(1,'age', '42');
INSERT 0 1
postgres=# INSERT INTO attr VALUES(2,'name','john');
INSERT 0 1
postgres=# INSERT INTO attr VALUES(2,'age', '22');
INSERT 0 1
postgres=# INSERT INTO attr VALUES(2,'favoritecolor','red');
INSERT 0 1
postgres=#
postgres=# SELECT systemid
postgres-# ,array_agg( name || '=' || value) AS profile_data
postgres-# FROM attr
postgres-# GROUP BY systemid;
systemid | profile_data
----------+--------------------------------------
1 | {name=ben,age=42}
2 | {name=john,age=22,favoritecolor=red}
(2 rows)
Or you can look into hstore or json data types.
Upvotes: 1