Ok please excuse the slightly strange example, but I couldn't think of anything better and my real SQL query would overcomplicate the essence of the real question...
Lets imagine I have 3 tables: - Person (PersonID, PersonName, DoB, etc) - PersonItemKey (PersonItemKeyID, ItemName) - PersonItemValue (PersonItemValueID, PersonItemKeyID, PersonID, Value)
So we could have Item keys for "Socks", "Jumpers", "T-Shirts, and Item Values that say that a particular person has say 10 pairs of sock, 6 jumpers and 8 shirts.
I can get this information with a query something like this:
SELECT *
FROM Person
LEFT JOIN PersonItemValue ON PersonItemValue.PersonID = Person.PersonID
INNER JOIN PersonItemKey ON PersonItemValue.PersonItemKeyID = PersonItemKey.PersonItemKeyID
The problem is that this would return 3 rows, each with the same PersonID, Name, DoB etc, but with different ItemName and Value fields (One for Socks, one for Jumpers and one for Shirts).
Is it possible to return a single row instead and promote the keys to field names and values to its value. i.e. make it so that "Socks" becomes a field name and 10 is its value, "Jumpers" is another field with 6 as its value, and "Shirts" as another field with a value of 8?
I've managed to do this in code in PHP like this:
$sql = "SELECT *
FROM Person
LEFT JOIN PersonItemValue ON PersonItemValue.PersonID = Person.PersonID
INNER JOIN PersonItemKey ON PersonItemValue.PersonItemKeyID = PersonItemKey.PersonItemKeyID";
// Run the query
$query = $db->query($sql);
// Convert it to a map
$allrows = array();
while($row = $query->fetch(PDO::FETCH_ASSOC))
{
// Create the entry if it doesn't exist
$key = $row['PersonID'];
if (isset($allrows[$key]) == false)
{
$allrows[$key] = $row;
}
// Turn ItemName into a field, and set its value
$field_name = $row['ItemName'];
$field_value = $row['Value'];
// Put the metric into the row
$allrows[$key][$field_name] = $field_value;
}
But it'd be better to do it in the query itself.
Is this possible?
Thanks in advance.
P.S. I don't believe that this is a duplicate of MySQL pivot row into dynamic number of columns as that uses Aggregate functions (count). At least I couldn't get it to work in my case.