任务:对于每件商品,找到价格最贵的经销商或经销商。

    这个问题可以用这样的子查询来解决:

    1. SELECT article, dealer, price
    2. FROM shop s1
    3. WHERE price=(SELECT MAX(s2.price)
    4. FROM shop s2
    5. WHERE s1.article = s2.article)
    6. ORDER BY article;
    7. +---------+--------+-------+
    8. | article | dealer | price |
    9. +---------+--------+-------+
    10. | 0001 | B | 3.99 |
    11. | 0002 | A | 10.99 |
    12. | 0003 | C | 1.69 |
    13. | 0004 | D | 19.95 |
    14. +---------+--------+-------+

    前面的示例使用了相关的子查询,这可能是低效的(请参阅第 13.2.11.7 节,“相关子查询”)。解决该问题的其他可能性是在 FROM 子句中使用不相关的子查询、LEFT JOIN 或带有窗口函数的公用表表达式。

    不相关子查询:

    1. SELECT s1.article, dealer, s1.price
    2. FROM shop s1
    3. JOIN (
    4. SELECT article, MAX(price) AS price
    5. FROM shop
    6. GROUP BY article) AS s2
    7. ON s1.article = s2.article AND s1.price = s2.price
    8. ORDER BY article;

    LEFT JOIN:

    1. SELECT s1.article, s1.dealer, s1.price
    2. FROM shop s1
    3. LEFT JOIN shop s2 ON s1.article = s2.article AND s1.price < s2.price
    4. WHERE s2.article IS NULL
    5. ORDER BY s1.article;

    LEFT JOIN 的工作原理是,当 s1.price 处于最大值时,没有更大的 s2.price,因此对应的 s2.article 值为 NULL。

    带窗函数的常用表表达式:

    1. WITH s1 AS (
    2. SELECT article, dealer, price,
    3. RANK() OVER (PARTITION BY article
    4. ORDER BY price DESC
    5. ) AS `Rank`
    6. FROM shop
    7. )
    8. SELECT article, dealer, price
    9. FROM s1
    10. WHERE `Rank` = 1
    11. ORDER BY article;