I have this two queries:
SELECT `a`.*, `b`.`id` AS host_id, SUM(CASE WHEN c.event_id IS NOT NULL THEN 1 ELSE 0 END) AS count_joins, SUM(CASE WHEN c.event_id IS NOT NULL AND c.user_id = 0 THEN 1 ELSE 0 END) AS joined
FROM (`events` AS a)
INNER JOIN `users` AS b ON `b`.`id` = `a`.`host_id`
LEFT JOIN `joins` AS c ON `c`.`event_id` = `a`.`id`
WHERE `a`.`date` > '2012-07-12 11:51:34'
GROUP BY `a`.`id`
ORDER BY `a`.`date` ASC
LIMIT 20
and
SELECT `b`.`id`, `b`.`first_name`, `b`.`last_name`, `b`.`email`, `b`.`username`, `b`.`thumbnail`
FROM (`joins` AS a)
INNER JOIN `users` AS b ON `b`.`id` = `a`.`user_id`
WHERE `a`.`event_id` = '1'
AND `a`.`user_id` != 0
ORDER BY RAND()
LIMIT 8
The first one get all events, then, using a foreach loop, I get the joins of each event with the second query.
My question is, how can I do all that with a single query?
Here is my schema:

I’d like to return a multidimensional array, for example:
Array
(
[0] => Array
(
[id] => 1
[title] => Title
[description] => DescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescriptionDescription
[segment] => title
[thumbnail] => 356a192b7913b04c54574d18c28d46e6395428ab.jpeg
[cover] => 356a192b7913b04c54574d18c28d46e6395428ab.jpeg
[locale] => Locale
[address] => Rua Afonso Pena, 22, Tijuca
[list] => 0
[date] => 2013-10-10 10:10:10
[created] =>
[host_id] => 1
[count_joins] => 5
[joined] => 0
[joins] => Array
(
[0] => Array
(
[id] => 4
[first_name] => Giovanna
[last_name] => Carneiro
[email] => gigi@gmail.com
[username] => gigi
[thumbnail] => 1b6453892473a467d07372d45eb05abc2031647a.jpg
)
[1] => Array
(
[id] => 5
[first_name] => Júlio
[last_name] => César
[email] => jujuba@gmail.com
[username] => jujuba
[thumbnail] => ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4.jpg
)
[2] => Array
(
[id] => 3
[first_name] => Claudio
[last_name] => Cardozo
[email] => cazo66@gmail.com
[username] => cazo
[thumbnail] => 77de68daecd823babbb58edb1c8e14d7106e83bb.jpg
)
[3] => Array
(
[id] => 1
[first_name] => Claudius
[last_name] => Ibn
[email] => ibnclaudius@gmail.com
[username] => ibnclaudius
[thumbnail] => 356a192b7913b04c54574d18c28d46e6395428ab.jpeg
)
[4] => Array
(
[id] => 2
[first_name] => Elza
[last_name] => Virginia
[email] => elza.mosqueira@gmail.com
[username] => elzavirginia
[thumbnail] => da4b9237bacccdf19c0760cab7aec4a8359010b0.jpg
)
)
)
[1] => Array
(
[id] => 2
[title] => Another Title
[description] => Description
[segment] => another-title
[thumbnail] => da4b9237bacccdf19c0760cab7aec4a8359010b0.jpeg
[cover] => da4b9237bacccdf19c0760cab7aec4a8359010b0.jpeg
[locale] => Locale
[address] => Travessa Nestor Vitor, 117, Tijuca
[list] => 0
[date] => 2013-10-10 10:10:10
[created] =>
[host_id] => 3
[count_joins] => 5
[joined] => 0
[joins] => Array
(
[0] => Array
(
[id] => 1
[first_name] => Claudius
[last_name] => Ibn
[email] => ibnclaudius@gmail.com
[username] => ibnclaudius
[thumbnail] => 356a192b7913b04c54574d18c28d46e6395428ab.jpeg
)
[1] => Array
(
[id] => 4
[first_name] => Giovanna
[last_name] => Carneiro
[email] => gigi@gmail.com
[username] => gigi
[thumbnail] => 1b6453892473a467d07372d45eb05abc2031647a.jpg
)
[2] => Array
(
[id] => 3
[first_name] => Claudio
[last_name] => Cardozo
[email] => cazo66@gmail.com
[username] => cazo
[thumbnail] => 77de68daecd823babbb58edb1c8e14d7106e83bb.jpg
)
[3] => Array
(
[id] => 5
[first_name] => Júlio
[last_name] => César
[email] => jujuba@gmail.com
[username] => jujuba
[thumbnail] => ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4.jpg
)
[4] => Array
(
[id] => 2
[first_name] => Elza
[last_name] => Virginia
[email] => elza.mosqueira@gmail.com
[username] => elzavirginia
[thumbnail] => da4b9237bacccdf19c0760cab7aec4a8359010b0.jpg
)
)
)
)
The first query return the events, the second the joins. I’d like to return everything, if possible, with only ONE query.
One of the issues with pure SQL is that you can’t create nested results in a single query. You can only return flat records with all the fields. You would then use your application layer to parse the records into nested rows.
If you are using ORMs like linq or Hibernate, all the work goes into the background.
You can get a result like:
events.id| events.title| events.locale| users.id| users.first_name| users.last_name
which, in your case, would return 10 distinct records, where fields from event would be duplicated in each record. Your application server would then parse that into the nested array.
I’ve written queries both ways, where I get a flat record, the way that I’ve described it, and parsed it on the application server, and where I do an initial query for the events, and separate query for each event, again from the application server. They both work, it’s just a question of whether it’s simpler/faster in your case to get the events, then their users, or to get all the data and then parse it.