SQLZOO:子查询中的派生表与子查询中的派生表?

时间:2018-11-07 21:35:32

标签: sql

https://sqlzoo.net/wiki/SELECT_within_SELECT_Tutorial的问题7

“查找每个大洲中最大的国家(按地区),显示大洲,名称和区域:”

我对为什么感到困惑

SELECT continent, name, area FROM world
  WHERE area >= ALL
    (SELECT area FROM world as x
        WHERE x.continent IN (continent))

结果:

+-----------+--------+----------+
| continent |   name |    area  |
+-----------+--------+----------+
| Eurasia   | Russia | 17125242 |
+-----------+--------+----------+

但是

SELECT continent, name, area FROM world as x
  WHERE area >= ALL
    (SELECT area FROM world 
        WHERE x.continent IN (continent))

OR

SELECT continent, name, area FROM world as x
  WHERE area >= ALL
    (SELECT area FROM world as y
        WHERE x.continent IN (y.continent))

两者都给出了正确的结果:

+---------------+------------+----------+
|   continent   |    name    |   area   |
+---------------+------------+----------+
| Africa        | Algeria    |  2381741 |
| Oceania       | Australia  |  7692024 |
| South America | Brazil     |  8515767 |
| North America | Canada     |  9984670 |
| Asia          | China      |  9596961 |
| Caribbean     | Cuba       |   109884 |
| Europe        | Kazakhstan |  2724900 |
| Eurasia       | Russia     | 17125242 |
+---------------+------------+----------+

我不明白为什么在子查询内部具有派生表与在子查询外部具有派生表有何不同。他们不应该都一样吗?

3 个答案:

答案 0 :(得分:1)

您的查询:

SELECT continent, name, area FROM world
  WHERE area >= ALL
    (SELECT area FROM world as x
        WHERE x.continent IN (continent))

与以下相同:

SELECT continent, name, area FROM world
  WHERE area >= ALL
    (SELECT area FROM world as x
        WHERE x.continent IN (x.continent))
<=>
SELECT continent, name, area FROM world
  WHERE area >= ALL(SELECT area FROM world as x)
--(assuming that continent is defined as NOT NULL)
-- In result you are searching for biggest country(correct answer - Russia)

为避免这种情况,您应该显式添加列名的前缀:

SELECT continent, name, area FROM world
  WHERE area >= ALL
    (SELECT area FROM world as x
        WHERE x.continent IN (continent))
=>
SELECT continent, name, area FROM world
WHERE area >= ALL
    (SELECT x.area FROM world as x
        WHERE x.continent IN (world.continent))

答案 1 :(得分:1)

长评论.. IN()的使用确实让我感到非常恐惧和愤怒。通常的写法是:

SELECT continent, name, area 
FROM world x
WHERE area >= ALL
    (SELECT area 
     FROM world y 
     WHERE x.continent = y.continent)

它是在行级别进行比较(也就是1:1值比较),因此使用IN()会产生误导,尤其是考虑到源代码是学习SQL的教程的人。

无论如何,请参阅卢卡兹(Lukasz)的答案,以很好地回答/说明您所看到的差异。

答案 2 :(得分:0)

行为不同是因为在第一个示例中,外部查询和内部查询之间在Continent上没有联接。

在第二和第三查询中,x是外部查询中的world表的别名,内部查询中指定x.Continent IN (continent)会限制内部查询返回的行到与外部查询中每行上的Continent值匹配的值。

在第一个查询中,您只是在内部表中别名world表,并且内部查询和外部查询中的Continent值之间没有链接,因此> =运算符被有效地应用于World表中的所有记录,这意味着您只会获得返回值最大的行。