2013-02-05 64 views
1

考虑从酒吧和啤酒数据库下面的关系找到的名称:找到最低价格的啤酒,可以在任何酒吧

销售(酒吧,啤酒价格):指在每个销售啤酒的价格每个酒吧(请注意,每个酒吧可以卖很多啤酒,许多酒吧可能以不同的价格出售相同的啤酒)。

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

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

嗨,我慢慢学习SQL,我无法理解的部分 “si.price < = s.price”。整个查询不会总是返回一个空表,因为嵌套select基本上是比较相同的两个表吗?

+3

我可以给你答案,而无需数据库:d – Sebas

+0

答案是已经在那里,我只是想明白它。 – Ricecooker

+0

将一些数据放到[小提琴](http://sqlfiddle.com)中,因为它可以更容易地看到什么是什么,并探索您的问题。 – hd1

回答

3

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

工作,它应该是:

... 
WHERE si.price < s.price) 


假设做出改变,它是如何工作的解释s表示内部查询表中的每一行执行一次,依赖于外表(称为“共同相关的子查询”)。因为在内部查询中使用了同一个表,所以您需要别名外部表(在本例中为“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 
+0

+1。 。 。接得好。 –

+0

+1很好的答案 –

+0

这是一个很好的解释非常感谢你。这让我更清楚了。 – Ricecooker

1
SELECT s.beer, s.price 
FROM sells s 
GROUP BY s.beer 
HAVING s.price = MIN(s.price) 

FIDDLE:http://sqlfiddle.com/#!2/f292c/1

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

1

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

但是,由于<=,写入的查询将不会返回任何内容。这应该是<

然而,有一个更简单的写这个查询方式:

select * 
from sells 
order by price 
limit 1 

运气最好的学习SQL。

+0

不,这将返回按价格排序的所有记录,而不是每个栏中的最低价格。 –

+0

@MarlinPierce我认为OP希望横跨所有酒吧的最低价格,而不是每个酒吧的最低价格......我将其基于他尝试查询的意图。 –

+0

问题是“可以在任何酒吧找到的最低价格啤酒”而不是“在每个酒吧可以找到的最低价格啤酒”。另外,示例查询接近于在所有酒吧中找到最小值。我坚持我的解释,除非提问者澄清了这一点。 –

0

只是ORDER BY以升序方式的价格和限制结果集到一个项目:

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

这将是* ANY *栏中的最低价格,而不是* EVERY *栏中的每个最低价格。 –

+1

@MarlinPierce这个问题要求在任何酒吧的最低价格的啤酒,而不是在每个酒吧的最低价格的啤酒。 –

+0

我想你是对的。 –