I am trying to sort the results of a query by the order present in the associative table. I have three tables:
restaurant_user_view
contains a row for each time a user has viewed a restaurant. The tables, in a simplified version, have this structure:
restaurants:
| id | name |
|----|------|
| 1 | Restaurant A|
| 2 | Restaurant B|
| 3 | Restaurant C|
| 4 | Restaurant D|
users:
| id | name |
|----|------|
| 1 | User A|
restaurant_user_view:
| id | user_id | restaurant_id | Timestamp |
|----|---------|---------------|-----------|
| 1 | 1 | 1 | xxxxx |
| 2 | 1 | 3 | xxxxx |
| 3 | 1 | 4 | xxxxx |
| 4 | 1 | 3 | xxxxx |
| 5 | 1 | 2 | xxxxx |
| 6 | 1 | 3 | xxxxx |
| 7 | 1 | 1 | xxxxx |
| 8 | 1 | 1 | xxxxx |
At the semantic level, I would like to have the last 3 restaurants visited, so the expected output is: Restaurant A, C, B with the restaurant_id
in restaurant_user_view
table: 1, 3, 2. The restaurant_user_view
id
is: 8, 6, 5.
I wrote this query:
SELECT restaurants.*, restaurant_user_view.timestamp
FROM restaurants
LEFT JOIN restaurant_user_view ON restaurants.id = restaurant_user_view.restaurant_id
WHERE restaurant_user_view.user_id = 1
GROUP BY restaurants.id
ORDER BY restaurant_user_view.timestamp DESC
But I get this output: restaurant_user_view.restaurant_id
: 2, 4, 3, because of those are the last visited restaurants after the group by
statement.
I haven't found any solution online, from what I have understood the problem lies in how the group by is handled by mysql. Any solutions?
You can do the aggregation in a derived table to get the maximum timestamp (ie the youngest visit) for each restaurant. Join in the outer query and use ORDER BY
and LIMIT
to get only the youngest three visits.
SELECT r.*,
x.timestamp
FROM (SELECT ru.restaurant_id,
max(ru.timestamp) timestamp
FROM restaurant_user_view ru
WHERE ru.user_id = 1
GROUP BY ru.restaurant_id) x
INNER JOIN restaurants r
ON r.id = x.restaurant_id
ORDER BY x.timestamp DESC
LIMIT 3;
Note: Besides not solving your problem, your query is malformed. There are columns in the list of selected columns that neither are in the GROUP BY
clause nor an argument to an aggregation function. Sadly instances of old MySQL versions or badly configured ones accept such erroneous queries. But the result can suddenly be funny.
Also note: A timestamp should not be an integer
. There are datetime
and timestamp
data types in MySQL. They, unlike integer
s allow date/time arithmetic on them.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.