从酒吧和啤酒数据库中考虑以下关系:
出售(酒吧、啤酒、价格):表示每个酒吧出售的每种啤酒的价格(注意,每个酒吧可以出售许多啤酒,许多酒吧可以出售同一种啤酒,价格可能不同)。
下面的查询查找可以在任何酒吧找到的最低价格啤酒的名称。
SELECT s.beer
FROM sells s
WHERE NOT EXISTS (SELECT si.beer
FROM sells si
WHERE si.price <= s.price)
嗨,我学习sql的速度很慢,我对“s I.price
最佳答案
这个查询中有一个错误-它永远不会返回任何行,因为没有价格不等于它本身。
要工作,应该是:
...
WHERE si.price < s.price)
假设进行了更改,那么对其工作原理的解释是,内部查询对表中的每一行执行一次,并依赖于外部表(称为“关联子查询”)。因为内部查询中使用了同一个表,所以需要对外部表进行别名(在本例中为“s”)。内部查询断言没有(其他)价格低于正在执行的行中的价格。
顺便说一下,不需要对内部查询进行别名处理—您可以删除“s1”,它仍然可以工作,因为内部查询是默认范围:
SELECT beer
FROM sells s
WHERE NOT EXISTS (
SELECT *
FROM sells -- no alias needed
WHERE price <= s.price)
此外,这是一个“坏”查询,因为correlated子查询导致执行“n”查询(每行一个)。最好使用
min()
聚合函数:SELECT beer
FROM sells
WHERE price = (SELECT min(price) FROM sells)
除了这个查询更简单、更容易理解(两件好事),它执行得更快,因为只执行两个查询(一个子查询查找最低价格,一个子查询获取拥有它的整行)。
最后,最后一个(尽管很小)缺陷是,如果有多个价格相同的低价啤酒,所有这些都将返回多行。要返回最低价格的啤酒,您需要将行数限制为1,并决定如何打破平局(可能是在名称上)。实际上,只返回一行就可以进行更简单的查询:
select beer
FROM sells
ORDER BY price
LIMIT 1
如果你需要不断打破平局(即不随机返回相同价格和相同最低价格的啤酒),也可以按名称订购:
select beer
FROM sells
ORDER BY price, beer
LIMIT 1