【问题标题】:Find the name of the minimum price beer that can be found at any bar查找可以在任何酒吧找到的最低价格啤酒的名称
【发布时间】:2013-02-06 05:43:00
【问题描述】:

考虑 Bars and Beers 数据库中的以下关系:

sells(bar, beer, price):表示在每个酒吧销售的每种啤酒的价格(注意,每个酒吧可以卖很多啤酒,很多酒吧可以卖同一种啤酒,价格可能不同)。

以下查询查找可以在任何酒吧找到的最低价格啤酒的名称。

SELECT s.beer
FROM sells s
WHERE NOT EXISTS (SELECT si.beer
FROM sells si
WHERE si.price <= s.price) 

您好,我正在慢慢学习 sql,我无法理解“si.price

【问题讨论】:

  • 我可以在没有数据库的情况下给你答案:D
  • 答案已经有了,我只是想弄明白。
  • 将一些数据放入fiddle,这样可以更轻松地查看内容并探索您的问题。

标签: mysql sql


【解决方案1】:

该查询中有一个错误 - 它永远不会返回任何行,因为没有价格不等于自身。

要工作,应该是:

...
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)

此外,这是一个“坏”查询,因为相关子查询会导致执行“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

【讨论】:

  • 这是一个很好的解释,非常感谢。这让我现在更清楚了。
  • 没问题。有一天你可以给我那杯啤酒:)
  • 轻微错误查询2应该是SELECT s.beer FROM sells s WHERE price = (SELECT min(price) FROM sells)
  • @davidstrachan 谢谢。实际上,“s”。任何地方都不需要 - 我已在所有查询中将其更改为 SELECT beer
【解决方案2】:

嵌套查询正在比较相同的两个表。但是,它实际上更像是从表中取出一行,将其与表中的所有其他行进行比较,然后继续下一行。这是一个概念的解释。实际的实现可能完全不同。

但是,由于&lt;=,所编写的查询不会返回任何内容。这应该是&lt;

但是,有一个更简单的方法来编写这个查询:

select *
from sells
order by price
limit 1

祝你学习 SQL 好运。

【讨论】:

  • 不,这将返回按价格排序的所有记录,而不是每个柱中的最低价格。
  • @MarlinPierce 我认为 OP 想要所有柱的最低价格,而不是每根柱的最低价格......我是基于他尝试查询的意图。
  • 问题是“可以在任何酒吧找到的最低价格啤酒”而不是“可以在每个酒吧找到的最低价格啤酒”。此外,示例查询接近于找到所有条形图的最小值。我坚持我的解释,除非提问者澄清了这一点。
【解决方案3】:
SELECT s.beer, s.price
FROM sells s
GROUP BY s.beer
HAVING s.price = MIN(s.price)

小提琴:http://sqlfiddle.com/#!2/f292c/1

请注意,这不是标准的。 Mysql 允许不按选定的列进行分组。

【讨论】:

    【解决方案4】:

    只需按价格按升序排序并将结果集限制为一项:

    SELECT bar, beer, price FROM sells ORDER BY price ASC LIMIT 1
    

    【讨论】:

    • 这将是 ANY 条中的最低价格,而不是 EVERY 条中的每个最低价格。
    • @MarlinPierce 这个问题要求的是任何酒吧的最低价格啤酒,而不是每个酒吧的最低价格啤酒。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-26
    • 2014-08-03
    • 1970-01-01
    • 2014-01-10
    • 2016-08-22
    • 1970-01-01
    • 2023-03-26
    相关资源
    最近更新 更多