【问题标题】:NOT IN vs IN Do Not Return Complimentary ResultsNOT IN vs IN 不返回免费结果
【发布时间】:2013-05-14 19:29:17
【问题描述】:

您好,我正在研究 sql zoo 教程中的示例 #7:SELECT within SELECT。在下面的问题中

“查找属于所有人口少于 25000000 的大陆的每个国家/地区。显示名称、大陆和人口。”

我通过使用 NOT IN 和这样的子查询得到正确答案:

SELECT name, continent, population FROM world 
WHERE continent NOT IN (
    SELECT continent FROM world
    WHERE population > 25000000)

另一方面,如果我使用“IN”而不是“NOT IN”和“population

【问题讨论】:

  • 您检查过各个子查询的结果吗?
  • "population 25000000" 并未涵盖所有情况。
  • 你应该使用NOT EXISTS
  • 为什么在这里使用子查询???
  • 如果我没看错的话,问题是要列出一个大陆上每个国家的人口都低于 25000000 的每个国家,对吗?如果是,请查看您的子查询。您正在拉动每个国家/地区人口超过 25000000 的大陆,因此排除这些就是它起作用的原因。如果你走另一条路,如果任何国家低于 25000000,它将显示大陆,但你只想要它,如果每个国家都低于。

标签: sql


【解决方案1】:

如果我没看错的话,问题是要列出一个大陆上的每个国家,其中每个国家的人口都低于 25000000,对吗?

如果是,请查看您的子查询:

SELECT continent FROM world
WHERE population > 25000000

您正在拉动至少有一个国家/地区人口超过 25000000 的每个大陆,因此排除这些就是它起作用的原因。

示例:Alpha 大陆有 5 个国家,其中 4 个很小,但其中一个国家 Charlie 的人口为 50000000。

因此,您的子查询将返回 Continent Alpha,因为查理国家/地区符合​​人口 > 25000000 的约束。此子查询将找到您不想要的所有内容,这就是使用 not in 的原因。

另一方面:

SELECT continent FROM world
WHERE population > 25000000

如果任何国家/地区低于 25000000,它将显示大陆,这不是您想要的,因为您希望每个国家/地区都低于。

例子:之前的阿尔法大陆,四个小国。这四个低于 25000000,因此无论 Country Charlie 有 50000000,它们都将由您的子查询返回。

显然,这不是最好的方法,但这就是第一个查询有效而第二个无效的原因。

【讨论】:

  • 所以你是说通过使用“IN”,我可以得到每个大陆至少有一个人口少于 25000000 的国家,这可能是对的,谢谢。
  • 是的,这是正确的,因为子查询就是这样做的。抱歉,这不是最好的措辞。我已经对其进行了编辑以稍微清除它。
  • @Julian 是否可以指出哪种方式是解决您理解的问题的最佳方式?谢谢
【解决方案2】:

因为其他每个大陆都至少有一个国家的 Mio 人口少于 25。这就是它所说的。

  SELECT name, continent, population FROM world 
WHERE continent IN (
    SELECT continent FROM world
    WHERE population < 25000000)

将其翻译成文字:从所有国家的列表中(在世界表中),请找到该大陆拥有少于 25 个 Mio 人口的国家的所有国家。

【讨论】:

    【解决方案3】:

    为什么要使用子查询?

    尝试使用:

    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

    【讨论】:

      【解决方案4】:

      显示表格声明。看来您使用 CONTINENT 作为大陆号。然后你应该检查它是否标有 PRIMARY KEY 和 NOT NULL 选项。 我真的怀疑你只是忘记了 NULL 在 SQL 中的特殊含义。

      我在 Firebird 2.5.1 SQL server 中做了一个例子。

      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>
      

      【讨论】:

        猜你喜欢
        • 2017-02-06
        • 1970-01-01
        • 2019-05-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-10-14
        • 2021-12-29
        相关资源
        最近更新 更多