问题
Pretty straightforward SQL question here - I have three levels of data spread out over three tables. Table 1- Listings, Table 2 - Interests, Table 3 - Messages
Table 1 -> Table 2, and Table 2 -> Table 3 have a One-To-Many Relationship
There will always be listings, but there may or may not be interests for each listing, and there may or may not be messages for each interest.
What I want to do is select all the information in 1 Select Statement in order to avoid multiple database calls.
I know with two levels of information you can use GROUP_CONCAT and GROUP BY to grab all the second level information into a concatenated string column. I just don't know what to do with three levels if I want to use only one select. I also know how this can be done with two separate calls and a PHP/python script in between, but I want to avoid that for performance.
Ideally I would get back an array that looks like this:
array(
'1'=>array(listingId'=>1,
interests=>
array(
array(
'interestId'=>2
'messages'=>array(
'messageId'=>5,
'message'=>'hi'
),
...
),
...
),
...
),
...
)
Another ideal situation would be to get:
array(
'1'=>array(listingId'=>1,
interests=>
array(
array('interestId'=>2,
'messages'=>INSERT CONCATENATED STRING HERE
),
...
),
...
),
...
)
With this situation I could just use a PHP/Python/Ruby script to parse the concatenated string of message.
The dots represent more arrays with similar data.
The most significant problem with trying to use concatenation is that you can only pull back one column using a subselect.
Thanks in advance! :)
回答1:
Can't you just join all the tables?
SELECT * FROM table1, table2, table3 WHERE table3.ref=table2.id AND table2.ref=table1.id
I don't know which foreign index you use, so I just used ref
and id
.
[EDIT]
Another solution, in 1 call, is using different GROUP_CONCAT
instructions, with different separators, like this:
SELECT naam,GROUP_CONCAT(t4.messages SEPARATOR '#') FROM test_listing t1 LEFT JOIN (SELECT t2.id,t2.ref,GROUP_CONCAT(message SEPARATOR '=') as messages FROM test_message t3 RIGHT JOIN test_interest t2 ON t2.id=t3.ref GROUP BY t2.id) t4 ON t1.id=t4.ref GROUP BY t1.id
This will return as many records as you have listings, and then combines all messages with separator '=', after which it will combine all these with '#'
I don't see a more elegant solution to this problem ! Also, neither is there a more elegant solution on the topic Join Table To a nested array [PHP/MYSQL].
来源:https://stackoverflow.com/questions/26734737/multi-level-mysql-query-in-one-select-statement