NOT IN vs IN不退还免费结果

时间:2013-05-14 19:29:17

标签: sql

您好我正在使用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”我没有得到正确的答案,我无法理解为什么会这样,这可能是我的简单原因只是看不到它,有人能解释一下吗?

4 个答案:

答案 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

中使用“population”列

或者你想要这样做:

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>