您好我正在使用sql zoo教程中的示例#7:SELECT within SELECT。在以下问题中
“查找属于所有人口少于2500万的大陆的每个国家。显示名称,大陆和人口。”
我通过使用NOT IN和这样的子查询得到了正确的答案:
SELECT name, continent, population FROM world
WHERE continent NOT IN (
SELECT continent FROM world
WHERE population > 25000000)
如果我另一方面使用“IN”而不是“NOT IN”和“population< 25000000”我没有得到正确的答案,我无法理解为什么会这样,这可能是我的简单原因只是看不到它,有人能解释一下吗?
答案 0 :(得分:3)
如果我正确地阅读这个问题,那么问题就是要列出每个国家人口低于2500万的大陆上的每个国家,对吗?
如果是,请查看您的子查询:
SELECT continent FROM world
WHERE population > 25000000
你正在拉动每个拥有至少一个人口超过2500万的国家的大陆,所以排除这些就是它的原因。
示例:大陆阿尔法有5个国家,其中4个国家很小,但其中一个国家查理拥有5000万人口。
因此,您的子查询将返回Continent Alpha,因为国家/地区Charlie符合人口约束> 25000000.此子查询将找到您不想要的所有内容,这就是为什么使用not in将起作用。
另一方面:
SELECT continent FROM world
WHERE population > 25000000
如果任何国家/地区低于25000000,它将显示该大陆,这不是您想要的,因为您希望每个国家/地区都在下方。
示例:来自之前的大陆Alpha,四个小国家。这四个都低于25000000,因此无论Country Charlie是否拥有50000000,它们都会被您的子查询返回。
显然,这不是最好的方法,但这就是为什么第一个查询有效,第二个查询没有。
答案 1 :(得分:2)
因为每个其他大陆至少有一个国家的人口少于25万。这就是说的。
SELECT name, continent, population FROM world
WHERE continent IN (
SELECT continent FROM world
WHERE population < 25000000)
将其翻译成文字:从所有国家/地区的列表中(在表格世界中),请查找该大陆所在国家的人口少于25万的所有国家/地区。
答案 2 :(得分:0)
为什么要使用子查询?
尝试使用:
SELECT name, continent, population FROM world
WHERE population > 25000000
和/或
SELECT name, continent, population FROM world
WHERE population <= 25000000
你的条件栏:“人口”在FROM
表:“世界”。无需再次使用同一个表“world”的子查询,只需直接在WHERE
或者你想要这样做:
SELECT name, continent, population FROM world
WHERE continent NOT IN (
SELECT continent FROM world
GROUP BY continent
HAVING SUM(population) > 25000000)
注意:SUM(),GROUP BY和HAVING
答案 3 :(得分:0)
显示表DECLARATION。您似乎使用CONTINENT作为大陆号码。然后你应该检查它是否标有PRIMARY KEY和NOT NULL选项。 我怀疑你只是忘了在SQL中有非常特殊的含义。
我在Firebird 2.5.1 SQL服务器中做了一个例子。
CREATE TABLE WORLD (
CONTINENT INTEGER,
NAME VARCHAR(20),
POPULATION INTEGER
);
INSERT INTO WORLD (CONTINENT, NAME, POPULATION) VALUES (NULL, 'null-id', 100);
INSERT INTO WORLD (CONTINENT, NAME, POPULATION) VALUES (1, 'normal 1', 10);
INSERT INTO WORLD (CONTINENT, NAME, POPULATION) VALUES (2, 'normal 2', 200);
INSERT INTO WORLD (CONTINENT, NAME, POPULATION) VALUES (3, 'null-pop', NULL);
INSERT INTO WORLD (CONTINENT, NAME, POPULATION) VALUES (4, 'normal 4', 110);
COMMIT WORK;
现在让我们尝试你的请求,看看第一行是否有CONTINENT IS NULL:
SELECT continent, population FROM world
WHERE continent IN (
SELECT continent FROM world
WHERE population > 100)
CONTINENT POPULATION
2 200
4 110
然后
SELECT continent, population FROM world
WHERE continent NOT IN (
SELECT continent FROM world
WHERE population > 100)
CONTINENT POPULATION
1 10
3 <NULL>
根据请求的逻辑,您认为CONTINENT是行ID,那么您应该将其设为NOT-NULL,然后不会出现[NOT] IN条件下看不到的行。
现在,让我们将其重新用于平面查询:
SELECT continent, population FROM world
WHERE NOT (population > 100)
CONTINENT POPULATION
<NULL> 100
1 10
SELECT continent, population FROM world
WHERE population > 100
CONTINENT POPULATION
2 200
4 110
这次错过的行是人口列的NULL。
然后 FreshPrinceOfSO 建议使用EXISTS子句。虽然它可能以最慢(非有效)的查询计划结束,但它至少掩盖了SQL中NULL值的特殊含义。
SELECT continent, population FROM world w_ext
WHERE EXISTS (
SELECT continent FROM world w_int
WHERE (w_int.population > 100) and (w_int.continent = w_ext.continent)
)
CONTINENT POPULATION
2 200
4 110
SELECT continent, population FROM world w_ext
WHERE NOT EXISTS (
SELECT continent FROM world w_int
WHERE (w_int.population > 100) and (w_int.continent = w_ext.continent)
)
CONTINENT POPULATION
<NULL> 100
1 10
3 <NULL>