Reputation: 704
I have these two tables:
Table "items":
╔════╦══════════════╦═══════╗
║ ID ║ NAME ║ TYPE ║
╠════╬══════════════╬═══════╣
║ 1 ║ Home ║ House ║
║ 2 ║ Livingroom ║ Room ║
║ 3 ║ Kitchen ║ Room ║
║ 4 ║ Pots ║ Item ║
║ 5 ║ Pans ║ Item ║
║ 6 ║ Table ║ Item ║
║ 7 ║ Away ║ House ║
╚════╩══════════════╩═══════╝
Table "relationships":
╔════╦═══════════╦═══════════╗
║ ID ║ ITEM_ID ║ PARENT_ID ║
╠════╬═══════════╬═══════════╣
║ 1 ║ 2 ║ 1 ║
║ 2 ║ 3 ║ 1 ║
║ 3 ║ 4 ║ 3 ║
║ 4 ║ 5 ║ 3 ║
║ 5 ║ 6 ║ 2 ║
╚════╩═══════════╩═══════════╝
And I am building the following array in php:
$arr = array(
'1' => array(
'name' => 'Home',
'rooms' => array(
'2' => array(
'name' => 'livingroom',
'items' => array(
'6' => 'Table'
)
),
'3' => array(
'name' => 'kitchen',
'items' => array(
'4' => 'Pots',
'5' => 'Pans'
)
),
),
);
'7' => array(
'name' => 'Away',
'rooms' => array(
),
);
);
Currently the way this is done is by first doing a query on the items table for the houses:
SELECT
id,
name
FROM items
WHERE type = "House"';
Then a query on the relationships table that left joins the items table on item_id to get the name and the type.
SELECT
i.id AS id,
i.name AS name,
i.type AS type,
r.parent_id AS parent
FROM relationships r
LEFT JOIN items i
ON r.element_id = i.id';
And finally three foreach loops are used to build the array. One to structure the houses from the first query. then another to separate rooms and items, and a third to combine it all into the final array.
While it works I'm sure a better solution is possible for the query, such as combining the two into one for example. How could this query be combined into one and the array be built with as few loops as possible?
Upvotes: 1
Views: 321
Reputation: 5040
If you only have 3 nesting levels, this query will work to return the parents and their children:
SELECT
a.`ID`,
a.`NAME`,
a.`TYPE`,
c.`NAME`,
c.`TYPE`,
e.`NAME`,
e.`TYPE`
FROM `items` a
JOIN `relationships` b
ON a.`ID` = b.`ITEM_ID`
JOIN `items` c
ON b.`PARENT_ID` = c.`ID`
JOIN `relationships` d
ON b.`PARENT_ID` = d.`ITEM_ID`
JOIN `items` e
ON d.`PARENT_ID` = e.`ID`;
Upvotes: 1