views:

76

answers:

2

Given a table like this:

==============================================
| ID1 | ID2 | ID3 | Name          | Value    |
==============================================
| 16  | 1   | 100 | item_name     | Toys     |
| 16  | 2   | 101 | item_name     | Computer |
| 16  | 1   | 102 | item_price    | 55       |
| 16  | 2   | 103 | item_price    | 200      |
| 16  | 1   | 104 | animal_name   | dog      |
| 16  | 2   | 105 | animal_name   | cat      |
| 16  | 1   | 106 | animal_gender | male     |
| 16  | 2   | 107 | animal_gender | female   |
| 18  | 1   | 100 | item_name     | Toys     |
| 18  | 2   | 101 | item_name     | Computer |
| 18  | 1   | 102 | item_price    | 55       |
| 18  | 2   | 103 | item_price    | 200      |
| 18  | 1   | 104 | animal_name   | dog      |
| 18  | 2   | 105 | animal_name   | cat      |
| 18  | 1   | 106 | animal_gender | male     |
| 18  | 2   | 107 | animal_gender | female   |
----------------------------------------------

How do I use SQL to make it like this:

==============================================================
| ID1 | item_name | item_price | animal_name | animal_gender |
==============================================================
| 16  | Toys      | 55         | dog         | male          |
| 16  | Toys      | 55         | cat         | female        |
| 16  | Computer  | 200        | dog         | male          |
| 16  | Computer  | 200        | cat         | female        |
| 18  | Toys      | 55         | dog         | male          |
| 18  | Toys      | 55         | cat         | female        |
| 18  | Computer  | 200        | dog         | male          |
| 18  | Computer  | 200        | cat         | female        |
--------------------------------------------------------------

I will be creating the SQL query in PHP.

+1  A: 

Try this, for MySQL (doesn't work in ANSI SQL):

SELECT  
  ID1,  
  GROUP_CONCAT(if(Name = 'item_name', Value, NULL)) AS 'item_name', 
  GROUP_CONCAT(if(Name = 'item_price', Value, NULL)) AS 'item_price', 
  GROUP_CONCAT(if(Name = 'animal_name', Value, NULL)) AS 'animal_name', 
  GROUP_CONCAT(if(Name = 'animal_name', Value, NULL)) AS 'animal_name', 
FROM tbl 
GROUP BY ID1, ID2, ID3;

(Disclaimer: untested with your data.)

chryss
@chrss, got the same thing as Mark's suggestion: http://pastebin.com/u4fBLfWc. Any other ideas?
StackOverflowNewbie
+1  A: 

EDITED, following SONewbie's comments

Should be ANSI compliant:

SELECT  
  ID1,  
  MAX(CASE WHEN Name = 'item_name' THEN Value ELSE NULL END) AS item_name, 
  MAX(CASE WHEN Name = 'item_price' THEN Value ELSE NULL END) AS item_price, 
  MAX(CASE WHEN Name = 'animal_name' THEN Value ELSE NULL END) AS animal_name, 
  MAX(CASE WHEN Name = 'animal_gender' THEN Value ELSE NULL END) AS animal_gender
FROM tbl 
GROUP BY ID1, ID2;

This won't produce exactly the output desired - instead, the output will look like this:

==============================================================
| ID1 | item_name | item_price | animal_name | animal_gender |
==============================================================
| 16  | Toys      | 55         | dog         | male          |
| 18  | Toys      | 55         | dog         | male          |
| 16  | Computer  | 200        | cat         | female        |
| 18  | Computer  | 200        | cat         | female        |
--------------------------------------------------------------

This is because ID1 and ID2 link cat and female with Computer and 200 only, while the same fields link dog and male with Toys and 55 only. Grouping by ID3 introduces lots of NULLs, since ID1 and ID3 together uniquely identify the data rows.

Mark Bannister
@Mark, I'm getting NULLs in some cells. See: http://pastebin.com/u4fBLfWc. Any other ideas?
StackOverflowNewbie
@SONewbie, I've edited my query slightly so it doesn't produce NULLs with the data you originally provided - as described in the edited answer, it isn't an exact match for your requirements (which can't be matched for the data supplied). Additionally, the data in the output in your pastebin.com link don't match the data supplied with the question.
Mark Bannister