【问题标题】:how to sort order of LEFT JOIN in SQL query?如何在 SQL 查询中对 LEFT JOIN 的顺序进行排序?
【发布时间】:2011-07-18 08:31:31
【问题描述】:

好的,我尝试用谷歌搜索疯狂的答案,但我无法解决这个问题,所以我希望有人能够提供帮助。

假设我有一个用户表,非常简单的表:

id | userName
3    Michael
4    Mike
5    George

我还有另一张关于他们的汽车和价格的表格。

id | belongsToUser | carPrice
1    4               5000
2    4               6000
3    4               8000

现在我需要做的是这样的事情(随意重写):

   SELECT
      `userName`,
      `carPrice`
   FROM `users`
   LEFT JOIN `cars`
   ON cars.belongsToUser=users.id
   WHERE `id`='4'

返回:

Mike | 5000

但我需要某个用户最贵的车,而不是找到的第一个条目。

所以问题:如何设置 LEFT JOIN 表以按 carPrice、DESC 排序?

【问题讨论】:

  • 应该返回所有 3 条记录,为什么它只返回 1 条......我们错过了什么?
  • 你没有显示整个查询,它应该返回三个结果
  • 当您说“按 carPrice DESC 订购”时,您的意思是您想要所有匹配的汽车,按价格订购吗?还是您的意思是您希望加入只获得一辆匹配的汽车,而那辆汽车是最昂贵的?

标签: mysql sql greatest-n-per-group


【解决方案1】:

旧的 MySQL 版本就足够了:

SELECT
    `userName`,
    `carPrice`
FROM `users`
LEFT JOIN (SELECT * FROM `cars` ORDER BY `carPrice`) as `cars`
ON cars.belongsToUser=users.id
WHERE `id`='4'

现在,如果您使用 MariaDB,子查询应该是有限

SELECT
    `userName`,
    `carPrice`
FROM `users`
LEFT JOIN (SELECT * FROM `cars` ORDER BY `carPrice` LIMIT 18446744073709551615) as `cars`
ON cars.belongsToUser=users.id
WHERE `id`='4'

【讨论】:

  • 在你的答案中添加一个小解释通常很有用
  • 除非您别无选择,否则请始终尽量避免这样的子选择。这可能适用于小型数据集,但开始处理数千或数百万行时,您最多会遇到性能问题。
【解决方案2】:

这将为用户提供最昂贵的汽车:

SELECT users.userName, MAX(cars.carPrice)
FROM users
LEFT JOIN cars ON cars.belongsToUser=users.id
WHERE users.id=4
GROUP BY users.userName

但是,这句话让我觉得您希望所有汽车价格按降序排列:

所以问题:如何设置 LEFT JOIN 表以按 carPrice、DESC 排序?

所以你可以试试这个:

SELECT users.userName, cars.carPrice
FROM users
LEFT JOIN cars ON cars.belongsToUser=users.id
WHERE users.id=4
GROUP BY users.userName
ORDER BY users.userName ASC, cars.carPrice DESC

【讨论】:

    【解决方案3】:

    尝试使用MAXGROUP BY

    SELECT u.userName, MAX(c.carPrice)
    FROM users u
        LEFT JOIN cars c ON u.id = c.belongsToUser
    WHERE u.id = 4;
    GROUP BY u.userName;
    

    更多信息GROUP BY

    group by 子句用于根据 group by 列的唯一组合将所选记录分成组。然后,这允许我们使用将依次应用于每组记录的聚合函数(例如 MAX、MIN、SUM、AVG...)。数据库将为每个分组返回一条结果记录。

    例如,如果我们在这样的表中有一组表示温度随时间和位置变化的记录:

    Location   Time    Temperature
    --------   ----    -----------
    London     12:00          10.0
    Bristol    12:00          12.0
    Glasgow    12:00           5.0
    London     13:00          14.0
    Bristol    13:00          13.0
    Glasgow    13:00           7.0
    ...
    

    那么如果我们想通过位置找到最高温度,那么我们需要将温度记录分成多个组,其中特定组中的每个记录具有相同的位置。然后我们想找到每组的最高温度。执行此操作的查询如下:

    SELECT Location, MAX(Temperature)
    FROM Temperatures
    GROUP BY Location;
    

    【讨论】:

    • 感谢您的帮助,如果您能进一步解释 GROUP BY 的用途,因为没有它,查询似乎返回相同的数据
    • 添加了一些关于 group by 的进一步解释
    • 非常好的解决方案。结合 MAX() 和 GROUP BY 会产生一个我没有预料到但效果很好的结果。对于当 tableB 有多行并且您想要加入特定行时的 LEFT JOIN。谢谢!
    【解决方案4】:

    其他几个答案给出了使用 MAX 的解决方案。在某些情况下,使用聚合函数要么不可能,要么性能不佳。

    我经常使用的替代方法是在连接中使用相关子查询...

    SELECT
       `userName`,
       `carPrice`
    FROM `users`
    LEFT JOIN `cars`
    ON cars.id = (
      SELECT id FROM `cars` WHERE BelongsToUser = users.id ORDER BY carPrice DESC LIMIT 1
    )
    WHERE `id`='4'
    

    【讨论】:

    • 那些场景是什么(帮助人们在子查询和group by之间做出决定)?
    • 如果cars 表包含其他信息,例如品牌、型号、牌照等。此方法查找单个记录及其所有字段。 MAX() 方法只找到一个字段的值。这取决于问题的真正意图(最高价格)与(最高价格的汽车)
    【解决方案5】:

    试试这个:

       SELECT
          `userName`,
          `carPrice`
       FROM `users`
       LEFT JOIN `cars`
       ON cars.belongsToUser=users.id
       WHERE `id`='4'
       ORDER BY `carPrice` DESC
       LIMIT 1
    

    菲利克斯

    【讨论】:

    • ORDER BY carPrice DESC,你的意思是?这将适用于单个用户,是的。但不是多个。
    • @djacobson 他正在按用户 ID 进行过滤。所以 group by 是一个更通用的解决方案。另一方面,如果他真的一直按用户 ID 过滤,这是一个更快的解决方案
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-28
    • 1970-01-01
    相关资源
    最近更新 更多