1

こんにちは、SQL Zoo チュートリアルの例 7 に取り組んでいます: SELECT 内の SELECT。次の質問では

「すべての人口が 25000000 未満である大陸に属する国をそれぞれ見つけてください。名前、大陸、人口を表示してください。」

NOT IN と次のようなサブクエリを使用して、正しい答えを取得します。

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

一方、「NOT IN」と「population < 25000000」の代わりに「IN」を使用すると、正しい答えが得られず、その理由が理解できません。これにはおそらく単純な理由があります。見て、誰か説明してくれませんか?

4

4 に答える 4

3

私がこれを正しく読んでいれば、この質問は、すべての国が 25000000 未満の人口を持つ大陸のすべての国をリストするように求めていますね。正しいですか?

はいの場合は、サブクエリを見てください。

SELECT continent FROM world
WHERE population > 25000000

人口が 25000000 を超える国が少なくとも 1 つあるすべての大陸をプルしているため、それらを除外することが機能する理由です。

例: 大陸アルファには 5 つの国があり、そのうちの 4 つは小さな国ですが、そのうちの 1 つ、国チャーリーの人口は 5 億人です。

国 Charlie は人口 > 25000000 の制約に適合するため、サブクエリは Continent Alpha を返します。このサブクエリは不要なものをすべて検索します。

一方で:

SELECT continent FROM world
WHERE population > 25000000

いずれかの国が 25000000 未満の場合、大陸が表示されますが、これは希望するものではありません。すべての国を下にしたいからです。

例:以前の大陸アルファ、4 つの小さな国。これら 4 つは 25000000 未満であるため、Country Charlie が 50000000 であるという事実に関係なく、サブクエリによって返されます。

明らかに、これは最善の方法ではありませんが、これが最初のクエリが機能し、2 番目のクエリが機能しなかった理由です。

于 2013-05-14T19:44:38.057 に答える
2

他のすべての大陸には、人口が 2,500 万人未満の国が少なくとも 1 つあります。これがそう言っている。

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

それを言葉に翻訳する: すべての国のリスト (表の世界) から、大陸に人口が 2500 万人未満の国があるすべての国を見つけてください。

于 2013-05-14T19:50:03.757 に答える
0

表 DECLARATION を表示します。大陸番号として CONTINENT を使用しているようです。次に、PRIMARY KEY および NOT NULL オプションでマークされていることを確認する必要があります。SQL における NULL の非常に特別な意味を忘れてしまったのではないかと思います。

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>
于 2013-05-14T19:43:10.880 に答える
0

サブクエリを使用する理由

使用してみてください:

SELECT name, continent, population FROM world 
WHERE population > 25000000

および/または

SELECT name, continent, population FROM world 
WHERE population <= 25000000

あなたの条件の列:「人口」はFROM表:「世界」にあります。同じテーブル「世界」のサブクエリを再度使用する必要はありません。「人口」列を直接使用するだけです。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 に注目してください。

于 2013-05-14T19:39:36.367 に答える