为什么SQLite中的嵌套查询返回错误的值?

时间:2015-09-07 01:47:38

标签: 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 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;

我得到The Quad Las Vegas Resort & Casino|2

但如果我跑:

    select name 
    from (select name, min(stars) 
          from businesses 
          where ratings >= 400);

我得到Giada

我知道有一种方法可以用LIMIT X做到这一点,但为什么会出现这种情况呢?我忽略了SQLite解析器的某些内容吗?

3 个答案:

答案 0 :(得分:2)

SQLite docs中,它说:

  

如果SELECT语句是没有GROUP BY的聚合查询   子句,然后评估结果集中的每个聚合表达式   一次跨越整个数据集。每个非聚合表达式   对于任意选择的行,对结果集进行一次计算   数据集。每个使用相同的任意选择的行   非聚合表达。

换句话说,在这种情况下,您获得的实际名称纯粹是随机的,它与实际具有最小值stars的行没有任何关系。

根据SQL-92标准,在包含聚合表达式和非聚合表达式的查询中,所有非聚合表达式都必须出现在GROUP BY子句中。 SQL-2003有一组类似但更复杂的规则。这个blog article提供了摘要。

某些数据库允许进行包含聚合和非聚合表达式的查询,而不包含任何GROUP BY子句,或者没有包含在GROUP BY子句中的所有非聚合,但是您发现结果可能是不确定的。其他数据库将显示错误并拒绝运行查询。

很难就如何纠正您的查询提出具体建议,因为您尚未说明您想要获得的输出。如果您试图找出哪一行的最小值为stars,那么Juan的答案中的一个提案应该有效。

答案 1 :(得分:1)

问题是您的MIN()函数为stars带来了最小值,但不是该行的名称匹配。

SQL Fiddle Demo

您可以进行交叉加入

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

答案 2 :(得分:1)

SQLite 3.7.11或更高版本保证未聚合列的值来自与min()或max()匹配的行。

但是,除非您使用的是最新版本之一,否则查询计划程序将优化远离查询返回的min()/ max()值。 您必须列出最外层查询中的min(stars)