为什么SQLite中的嵌套查询返回错误的值?
我正在处理为什么SQLite中的嵌套查询返回错误的值?,sql,database,sqlite,Sql,Database,Sqlite,我正在处理sqlite3上的yelp数据集,我有一个模式如下: CREATE TABLE businesses (business_id text primary key, name text, full_address text, city text, stars decimal(1,1), ratings integer); 我运行以下查询: select name, stars from busine
sqlite3
上的yelp数据集,我有一个模式如下:
CREATE TABLE businesses
(business_id text primary key,
name text,
full_address text,
city text,
stars decimal(1,1),
ratings integer);
我运行以下查询:
select name, stars from businesses where ratings >= 400;
我得到以下信息:
Pho Kim Long |3.5
Pho So 1 |3.5
Ichiza |4
...
Guy Fieri |3.5
Giada |4
如果我跑步:
select name, min(stars) from businesses where ratings >= 400;
我得到了拉斯维加斯四区度假村和赌场| 2
但如果我跑步:
select name
from (select name, min(stars)
from businesses
where ratings >= 400);
我得到了贾达
我知道有一种方法可以通过
限制X
实现这一点,但为什么首先会发生这种情况?SQLite解析器有什么我忽略的地方吗?问题是您的MIN()
函数为stars
带来最小的值,但不是该行的名称匹配
你可以做交叉连接
SELECT name
FROM businesses b,
( SELECT min(stars) as MinValue
FROM businesses
WHERE ratings >= 400) as M
WHERE b.stars = M.MinValue;
或内部选择
SELECT name
FROM businesses b
WHERE b.stars = ( SELECT min(stars) as MinValue
FROM businesses
WHERE ratings >= 400);
在报告中,它说:
如果SELECT语句是没有GROUP BY的聚合查询
子句,然后计算结果集中的每个聚合表达式
一旦跨越整个数据集。中的每个非聚合表达式
结果集对任意选择的数据行计算一次
数据集。每一行使用相同的任意选择行
非聚合表达式
换句话说,您得到的实际名称完全是随机的。在本例中,它与实际最小值为星的行没有任何关系
根据SQL-92标准,在包含聚合表达式和非聚合表达式的查询中,所有非聚合表达式必须出现在GROUPBY子句中。SQL-2003有一组类似但稍微复杂的规则。这是一个总结
某些数据库允许在不包含任何GROUP BY子句或GROUP BY子句中不包含所有非聚合的情况下进行包含聚合和非聚合表达式的查询,但正如您所发现的,结果可能是不确定的。其他数据库将显示错误并拒绝运行查询
很难给出关于如何更正查询的具体建议,因为您没有说明要获得的输出。如果您试图找出哪一行的最小值为stars
,那么Juan回答中的一个建议应该有效。SQLite 3.7.11或更高版本保证未聚合列的值来自与min()或max()匹配的行
但是,除非您使用的是最新版本之一,否则如果查询中没有返回min()/max()值,则查询计划器将优化这些值。
您必须在最外层的查询中列出min(stars)
。这里的其他答案是正确的(因此被提升),但我不确定它们是否能让您从现在的位置到达想要的位置
为什么查询的结果不可预测?
通常,像MIN/MAX/COUNT这样的聚合函数与GROUPBY子句一起使用。例如:
-- Count the number of businesses per city
SELECT city, COUNT(1) FROM biz GROUP BY city;
-- Find the minimum rating of any business per city
SELECT city, MIN(stars) FROM biz GROUP BY city;
如果省略GROUPBY子句,但在查询中保留非聚合字段(“城市”),会发生什么情况?你只会得到一分钟,但会是哪个“城市”?如果两个或两个以上的城市因最低评级的企业而并列,该怎么办
-- Er, which city will it be?
SELECT city, MIN(stars) FROM biz;
一些RDBMS完全禁止这种构造,SQL规范也不允许这种构造。*但是,在这种情况下,SQLite和其他一些RDBMS将返回一行,在整个表中使用最低评级,并任意选择一个“城市”。你。实际上,根据RDBMS版本的不同,它甚至可能不表示任何正确聚合的结果。**正如您所看到的,SQLite有时可以自由选择一行,有时可以选择另一行
你应该做什么?
如果我理解,您希望选择评级最差的餐厅(最低的“星级”),但仅限于那些评论数至少为400的餐厅(“评级”)
两种工作之一:在所有记录中查找MIN(stars)
,其中评级>=400
,然后使用该值选择stars
等于该值的每个企业的名称。(在撰写本文时,SQL分析函数提供了更多的计算方法。)
*情况是这样的
**同样,SQLite的更高版本确实保证所选行与聚合函数匹配。也就是说,您得到的名称实际上具有MIN(stars)
评级。您应该在示例数据中包含评级和四元赌场
。此查询从评级>=400的企业中选择name,MIN(stars)在技术上不正确,因为它没有GROUP BY BY
子句。我认为您需要使用标准正确定义的查询来获得预期的结果result@cha您可以使用min()。我认为第一个更有效。我理解你说的像字段,min(另一个字段)
。但我想知道,在我的示例中如何使用MIN()
?或者也反对SQL标准?@JuanCarlosOropeza no您可以使用min():在子查询中不包含任何非聚合,因此不需要任何分组