根据关联表顺序对查询结果进行排序

时间:2021-06-27 00:16:30

标签: mysql sql

我正在尝试按照关联表中的顺序对查询结果进行排序。我有三张桌子:

  • 用户
  • 餐厅
  • restaurant_user_view

restaurant_user_view 包含用户每次浏览餐厅时的一行。在简化版本中,这些表具有以下结构:

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 |

在语义层面,我希望访问最后 3 家餐厅,因此预期输出为: Restaurant A, C, B with the restaurant_id in restaurant_user_view table: 1, 3, 2. restaurant_user_view id 是:8、6、5。

我写了这个查询:

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

但是我得到这个输出:restaurant_user_view.restaurant_id: 2, 4, 3,因为这些是 group by 语句之后最后访问的餐馆。

我没有在网上找到任何解决方案,据我了解问题在于mysql如何处理group by。有什么解决办法吗?

1 个答案:

答案 0 :(得分:1)

您可以在派生表中进行聚合以获得每个餐厅的最大时间戳(即最年轻的访问)。加入外部查询并使用 ORDER BYLIMIT 仅获取最年轻的三个访问。

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;

注意:除了不能解决您的问题,您的查询格式错误。所选列列表中有一些列既不在 GROUP BY 子句中,也不在聚合函数的参数中。遗憾的是,旧 MySQL 版本或配置不当的实例会接受此类错误查询。但结果可能突然很有趣。

另请注意:时间戳不应是 integer。 MySQL 中有 datetimetimestamp 数据类型。与 integer 不同,它们允许对它们进行日期/时间算术。