NULLと3値論理|テーブル・SELECT・条件抽出
このページはプロモーション(広告)を含みます。
テーブル・SELECT・条件抽出(中級・読む25分+演習35分)
この授業のゴール
- NULL(値がない・未記録・不明)と 0・空文字の違いを、具体例で説明できる
- IS NULL / IS NOT NULL を使って欠損の行を取り出し、
= NULLが誤りである理由を説明できる - 3値論理(真・偽・不明)の表を使って、WHERE の結果と NOT IN の落とし穴を予測できる
- COUNT・AVG・SUM がNULLをどう扱うかを理解し、COALESCE・NULLIF で目的に合った集計に直せる
仕事でどう使うか
現実のデータには、空欄が必ずあります。未入力、未計測、未到着、該当なし。SQLの NULL は、そうした「値がない」状態を表します。NULLを0や空文字と混ぜると、平均や件数がこっそりずれて、誰も気づかないまま意思決定に使われます。
| 路線 | この授業の使いどころ |
|---|---|
| DS(データサイエンティスト) | 平均・割合の分母に欠損を含めるか決める。欠損の割合を最初に確認する |
| ML(機械学習エンジニア) | 特徴量の欠損処理(0で埋める、平均で埋める、欠損フラグを付ける)の前に、欠損が「未記録」か「該当なし」かを区別する |
| DX(DX推進・AI企画) | 業務システムの必須項目・任意項目を定義し、KPIの分母に未入力をどう扱うか決める |
| RS(研究者) | 欠測の扱い(完全ケース分析、補完)の前提として、欠測の理由と量を記録する |
この授業は、モジュール テーブル・SELECT・条件抽出 の「判定ポイント」の中心です。NULLの比較、ANDとORの優先度、順序未指定を、すべて自分の言葉で説明できることを目指します。
前提
次の言葉を使います。不安があれば先に戻ってください。
- WHERE と AND/OR → WHEREと条件
- ORDER BY でのNULLの位置 → ORDER BYとLIMIT
- 真偽値(真と偽)と論理演算 → 真偽とAND・OR・NOT
- 割合と平均 → 数値・カテゴリ・日時・欠損
この授業では、これまでと同じ注文表 orders を使います。amount(金額)は注文4が0円、注文6がNULL。coupon_code(クーポン)は、注文1・3・4・6がNULL、注文7が空文字、注文2・5が SPRING、注文8が VIP です。
身近な状況:「クーポン未使用の注文は何件?」と「平均金額は?」
注文表の coupon_code を見ます。
| order_id | coupon_code | amount |
|---|---|---|
| 1 | NULL | 3000 |
| 2 | SPRING | 1200 |
| 3 | NULL | 2500 |
| 4 | NULL | 0 |
| 5 | SPRING | 1800 |
| 6 | NULL | NULL |
| 7 | (空文字 '') |
1200 |
| 8 | VIP | 4000 |
質問が2つあります。
- 「クーポンを使わなかった注文は何件か」。NULL の4件だけでしょうか? 注文7の空文字も「使っていない」と考えるのが自然では?
- 「平均注文金額はいくらか」。注文4は0円、注文6は金額不明です。この2件を平均に入れるか、入れないかで答えが変わります。
どちらも、NULLをどう扱うかの決めが必要です。決めずにSQLを書くと、SQLの規則が自動で(しかも黙って)決めてしまいます。この授業ではその規則と、自分で決める方法を学びます。
-- db: none
CREATE TABLE orders (
order_id INTEGER PRIMARY KEY,
customer_id INTEGER NOT NULL,
order_date TEXT NOT NULL,
status TEXT NOT NULL CHECK(status IN ('paid','cancelled','refunded')),
channel TEXT NOT NULL,
amount INTEGER,
coupon_code TEXT
);
INSERT INTO orders VALUES
(1,101,'2025-03-31','paid','web',3000,NULL),
(2,102,'2025-04-01','paid','app',1200,'SPRING'),
(3,101,'2025-04-01','cancelled','web',2500,NULL),
(4,103,'2025-04-10','paid','store',0,NULL),
(5,104,'2025-04-15','refunded','app',1800,'SPRING'),
(6,102,'2025-04-20','paid','web',NULL,NULL),
(7,105,'2025-04-30','paid','web',1200,''),
(8,103,'2025-05-01','paid','app',4000,'VIP');
SELECT COUNT(*) AS all_rows,
COUNT(amount) AS amount_not_null,
AVG(amount) AS avg_amount
FROM orders;
結果は 8、7、約1957.14 です。AVG は NULL の注文6を分母から除いています(合計13700 ÷ 7件)。
直感的な説明:NULLは「わからない」、0は「0だった」
次の3つは、見た目が似ていても別の意味です。
| 値 | 意味 | 例 |
|---|---|---|
| 0 | 0という値が記録された | 無料サンプル(注文4)。金額は0円 |
空文字 '' |
文字がない文字列が記録された | クーポン欄に何も入力せずに送信(注文7) |
| NULL | 値がない。未入力・未計測・該当なし・不明 | 金額が未記録(注文6)、クーポン未使用(注文1など) |
NULLを「わからない」と考えると、SQLの動きが直感的に読めます。
- 「わからない」=「わからない」は、同じかどうかもわからない(NULL = NULL は不明)。
- 「わからない」に10を足しても、答えはわからない(NULL + 10 は NULL)。
- 「わからない」が10より大きいかは、わからない(NULL > 10 は不明)。
そして WHERE は「真と確定した行だけ」を残します。「不明」の行は、真ではないので消えます。これが、NULLをめぐる誤りの根っこです。
たとえ話の限界:NULL は「未知の値」のこともあれば、「そもそも該当しない」こともあります(解約していない人の解約日)。同じNULLでも意味が違うため、列ごとに意味を確認し、定義書に書く必要があります。
正確な定義:3値論理・IS NULL・集計関数・COALESCE
SQLの条件は、真(TRUE)・偽(FALSE)・不明(UNKNOWN)の3つの値を取ります。NULLを含む比較は不明になります。
$$\text{NULL} = \text{NULL} \Rightarrow \text{UNKNOWN},\qquad \text{NULL} > 10 \Rightarrow \text{UNKNOWN}$$
論理演算の結果(Tは真、Fは偽、Uは不明):
| A | B | A AND B | A OR B |
|---|---|---|---|
| T | U | U | T |
| F | U | F | U |
| U | U | U | U |
| A | NOT A |
|---|---|
| T | F |
| F | T |
| U | U |
覚えるポイントは、「偽 AND 不明 = 偽」「真 OR 不明 = 真」「NOT 不明 = 不明」の3つです。
WHERE の規則:条件が真の行だけを残す。偽と不明の行は消える。
NULLの判定:列 IS NULL、列 IS NOT NULL。列 = NULL は常に不明になり、1行も残りません。
集計関数とNULL:
| 関数 | NULLの扱い |
|---|---|
COUNT(*) |
行を数える(NULLを含む行も1行) |
COUNT(列) |
NULLでない値の数 |
SUM(列)、AVG(列)、MIN、MAX |
NULLを無視して計算する。すべてNULLなら結果もNULL |
変換関数:
COALESCE(a, b, ...):左から見て最初のNULLでない値を返す。COALESCE(amount, 0)は、NULLを0に直す。NULLIF(a, b):a と b が等しければ NULL、違えば a を返す。NULLIF(coupon_code, '')は、空文字をNULLに直す。
0にしてよいのは、「未記録=0」と業務で決めた場合だけです。決めずに0にすると、不明な値を「0だった」と書き換えることになります。
段階付き例題:クーポン未使用の定義と、平均金額の3つの答え
問題A:クーポンを使わなかった注文の件数を求める。空文字の注文7も「使っていない」とみなす。
ステップ1:定義を決める。クーポン未使用 = coupon_code が NULL または 空文字。
ステップ2:NULLの判定を書く。coupon_code IS NULL。空文字は coupon_code = ''。
ステップ3:OR でつなぐ。coupon_code IS NULL OR coupon_code = ''。AND がないので括弧は不要だが、ほかの条件と組み合わせるときは括弧が必須。
-- db: none
CREATE TABLE orders (
order_id INTEGER PRIMARY KEY,
customer_id INTEGER NOT NULL,
order_date TEXT NOT NULL,
status TEXT NOT NULL CHECK(status IN ('paid','cancelled','refunded')),
channel TEXT NOT NULL,
amount INTEGER,
coupon_code TEXT
);
INSERT INTO orders VALUES
(1,101,'2025-03-31','paid','web',3000,NULL),
(2,102,'2025-04-01','paid','app',1200,'SPRING'),
(3,101,'2025-04-01','cancelled','web',2500,NULL),
(4,103,'2025-04-10','paid','store',0,NULL),
(5,104,'2025-04-15','refunded','app',1800,'SPRING'),
(6,102,'2025-04-20','paid','web',NULL,NULL),
(7,105,'2025-04-30','paid','web',1200,''),
(8,103,'2025-05-01','paid','app',4000,'VIP');
SELECT COUNT(*) AS no_coupon
FROM orders
WHERE coupon_code IS NULL OR coupon_code = '';
-- 参考:間違った書き方(= NULL)は0件になる
SELECT COUNT(*) AS wrong FROM orders WHERE coupon_code = NULL;
ステップ4:結果を読む。正しい件数は 5(注文1、3、4、6、7)。= NULL は 0。IS NULL だけでは注文7が漏れて4件になります。
問題B:平均注文金額を求める。ただし、金額の扱いで3通りの答えがある。
-- db: none
CREATE TABLE orders (
order_id INTEGER PRIMARY KEY,
customer_id INTEGER NOT NULL,
order_date TEXT NOT NULL,
status TEXT NOT NULL CHECK(status IN ('paid','cancelled','refunded')),
channel TEXT NOT NULL,
amount INTEGER,
coupon_code TEXT
);
INSERT INTO orders VALUES
(1,101,'2025-03-31','paid','web',3000,NULL),
(2,102,'2025-04-01','paid','app',1200,'SPRING'),
(3,101,'2025-04-01','cancelled','web',2500,NULL),
(4,103,'2025-04-10','paid','store',0,NULL),
(5,104,'2025-04-15','refunded','app',1800,'SPRING'),
(6,102,'2025-04-20','paid','web',NULL,NULL),
(7,105,'2025-04-30','paid','web',1200,''),
(8,103,'2025-05-01','paid','app',4000,'VIP');
SELECT AVG(amount) AS avg_ignore_null, -- NULLを無視(7件)
AVG(COALESCE(amount, 0)) AS avg_null_as_zero, -- NULLを0(8件)
(SELECT AVG(amount) FROM orders WHERE amount > 0) AS avg_positive_only -- 0円とNULLを除く(6件)
FROM orders;
ステップ5:結果を読む。合計は 13700 円です。
| 方法 | 分母 | 平均 |
|---|---|---|
| NULLを無視 | 7 | $13700 \div 7 \approx 1957.1$ |
| NULLを0として扱う | 8 | $13700 \div 8 = 1712.5$ |
| 0円とNULLを除く | 6 | $13700 \div 6 \approx 2283.3$ |
同じデータから、約1700円、約1960円、約2280円の3つが出ます。どれが正しいかは、「平均注文金額」の定義で決まります。たとえば、無料サンプルも1件の注文として数える方針なら、0円を含み、金額不明の1件だけを除く(約1957円)のが自然です。定義を決めず、SQLの既定(NULLを無視)に任せると、報告の数字を誰も説明できなくなります。
操作して理解する:3値論理の表を実行で確かめる
まず、真理値表を実行で確かめます。SQLiteでは、真が 1、偽が 0、不明が NULL(結果欄は空欄か「NULL」)で表示されます。実行する前に、各列の結果を予想してください。
-- db: none
SELECT NULL = NULL AS null_eq_null, -- 不明
NULL AND 0 AS u_and_f, -- 偽
NULL AND 1 AS u_and_t, -- 不明
NULL OR 1 AS u_or_t, -- 真
NULL OR 0 AS u_or_f, -- 不明
NOT NULL AS not_u; -- 不明
次に、WHERE の結果を予想します。
-- db: none
CREATE TABLE orders (
order_id INTEGER PRIMARY KEY,
customer_id INTEGER NOT NULL,
order_date TEXT NOT NULL,
status TEXT NOT NULL CHECK(status IN ('paid','cancelled','refunded')),
channel TEXT NOT NULL,
amount INTEGER,
coupon_code TEXT
);
INSERT INTO orders VALUES
(1,101,'2025-03-31','paid','web',3000,NULL),
(2,102,'2025-04-01','paid','app',1200,'SPRING'),
(3,101,'2025-04-01','cancelled','web',2500,NULL),
(4,103,'2025-04-10','paid','store',0,NULL),
(5,104,'2025-04-15','refunded','app',1800,'SPRING'),
(6,102,'2025-04-20','paid','web',NULL,NULL),
(7,105,'2025-04-30','paid','web',1200,''),
(8,103,'2025-05-01','paid','app',4000,'VIP');
-- (1) 「1200以上」と「1200未満」を足すと全件になる?
SELECT COUNT(*) AS n_ge_or_lt FROM orders WHERE amount >= 1200 OR amount < 1200;
-- (2) NULLの行を明示すると全件になる
SELECT COUNT(*) AS n_all FROM orders WHERE amount IS NULL OR amount >= 1200 OR amount < 1200;
-- (3) クーポンが SPRING でない注文(NULLを含めたい場合)
SELECT order_id FROM orders WHERE coupon_code IS NULL OR coupon_code <> 'SPRING' ORDER BY order_id;
-- (4) 空文字をNULLに寄せてから「なし」と表示する
SELECT order_id, COALESCE(NULLIF(coupon_code, ''), 'なし') AS coupon FROM orders ORDER BY order_id;
答えと読み方:
- (1) 7。注文6(NULL)は両方の条件で不明になり、除かれます。
- (2) 8。NULLを明示的に拾うと全件になります。
- (3) 注文 1、3、4、6、7、8。
<> 'SPRING'だけでは NULL が除かれますが、IS NULL ORで拾えます。 - (4) 注文7(空文字)も、NULLの注文も「なし」になります。注文2、5は
SPRING、注文8はVIP。
試してみよう:(3) の OR を AND に変えると、結果は0行になります。NULLの行は IS NULL を満たすが <> 'SPRING' は不明、AND の結果は不明、と3値論理の表どおりになるためです。
発展:NOT IN とNULL、NULLを同じとみなす場面、方言差
NOT IN の罠:x NOT IN (a, b, NULL) は、x が a でも b でもなくても、真にならず不明になります。x <> a AND x <> b AND x <> NULL と同じで、最後が不明のため全体が真になれないからです。サブクエリの結果にNULLが1つでも混ざると、NOT IN は1行も返さなくなります。対策は (1) サブクエリに WHERE 列 IS NOT NULL を付ける、(2) NOT EXISTS を使う(「サブクエリ」(有料版))、です。
NULLを同じとみなす場面:比較(=)では不明ですが、次の場面ではNULLどうしを「同じ」として扱います。
- DISTINCT:NULLの行は1つにまとめられる。
- GROUP BY:NULLは1つのグループになる。
- ORDER BY:NULLは連続して並ぶ(位置は方言による)。
- UNIQUE 制約:SQLiteや多くのデータベースでは、NULLは何個でも入れられる(方言差あり。SQL Server は1個まで)。
NULLを安全に比べる演算:SQLiteでは a IS b、a IS NOT b が、NULLを含めて等しいかを判定します(coupon_code IS NOT 'SPRING' は NULL の行も含めて真)。標準SQLでは IS DISTINCT FROM、IS NOT DISTINCT FROM で、PostgreSQL などが対応しています。書き方が方言で違うため、チームで使う方言の手順を確認してください。
欠測の理由と分析:統計では、欠測が「完全にランダム」「他の変数に依存」「値そのものに依存」の場合で、扱い方(除外、補完)が異なります。SQLでは単に除外されますが、除外した行が全体と性質が違うと、結果が偏ります(選択バイアス)。重要な分析では、欠損の割合と偏りを先に確認してください。
よくある失敗
失敗1:`= NULL` で欠損を探す
-- db: none
CREATE TABLE orders (
order_id INTEGER PRIMARY KEY,
customer_id INTEGER NOT NULL,
order_date TEXT NOT NULL,
status TEXT NOT NULL CHECK(status IN ('paid','cancelled','refunded')),
channel TEXT NOT NULL,
amount INTEGER,
coupon_code TEXT
);
INSERT INTO orders VALUES
(1,101,'2025-03-31','paid','web',3000,NULL),
(2,102,'2025-04-01','paid','app',1200,'SPRING'),
(3,101,'2025-04-01','cancelled','web',2500,NULL),
(4,103,'2025-04-10','paid','store',0,NULL),
(5,104,'2025-04-15','refunded','app',1800,'SPRING'),
(6,102,'2025-04-20','paid','web',NULL,NULL),
(7,105,'2025-04-30','paid','web',1200,''),
(8,103,'2025-05-01','paid','app',4000,'VIP');
-- 誤り:常に不明になり、0件
SELECT COUNT(*) AS wrong FROM orders WHERE amount = NULL;
-- 正しい
SELECT COUNT(*) AS right_n FROM orders WHERE amount IS NULL;
誤りは 0、正しくは 1(注文6)です。エラーが出ないため、「欠損はゼロ件」と誤って報告する危険があります。直し方:NULLの判定は常に IS NULL/IS NOT NULL。欠損の件数は COUNT(*) - COUNT(列) でも確認できる。
失敗2:NOT IN のリストにNULLが混ざって、全行が消える
-- db: none
CREATE TABLE orders (
order_id INTEGER PRIMARY KEY,
customer_id INTEGER NOT NULL,
order_date TEXT NOT NULL,
status TEXT NOT NULL CHECK(status IN ('paid','cancelled','refunded')),
channel TEXT NOT NULL,
amount INTEGER,
coupon_code TEXT
);
INSERT INTO orders VALUES
(1,101,'2025-03-31','paid','web',3000,NULL),
(2,102,'2025-04-01','paid','app',1200,'SPRING'),
(3,101,'2025-04-01','cancelled','web',2500,NULL),
(4,103,'2025-04-10','paid','store',0,NULL),
(5,104,'2025-04-15','refunded','app',1800,'SPRING'),
(6,102,'2025-04-20','paid','web',NULL,NULL),
(7,105,'2025-04-30','paid','web',1200,''),
(8,103,'2025-05-01','paid','app',4000,'VIP');CREATE TABLE flagged (customer_id INTEGER);
INSERT INTO flagged VALUES (104),(NULL);
-- 誤り:flagged に NULL が入っているため 0行
SELECT order_id FROM orders
WHERE customer_id NOT IN (SELECT customer_id FROM flagged);
-- 正しい:サブクエリでNULLを除く
SELECT order_id FROM orders
WHERE customer_id NOT IN (SELECT customer_id FROM flagged WHERE customer_id IS NOT NULL)
ORDER BY order_id;
要注意顧客のリスト flagged に、顧客104と、入力ミスのNULLが1行入っています。誤りのほうは 0行、正しいほうは顧客104以外の7件(注文 1、2、3、4、6、7、8)です。直し方:NOT IN の対象列にNULLが入らないことを確認するか、WHERE 列 IS NOT NULL で除く。
失敗3:NULLを黙って0にして、平均を下げる
-- db: none
CREATE TABLE orders (
order_id INTEGER PRIMARY KEY,
customer_id INTEGER NOT NULL,
order_date TEXT NOT NULL,
status TEXT NOT NULL CHECK(status IN ('paid','cancelled','refunded')),
channel TEXT NOT NULL,
amount INTEGER,
coupon_code TEXT
);
INSERT INTO orders VALUES
(1,101,'2025-03-31','paid','web',3000,NULL),
(2,102,'2025-04-01','paid','app',1200,'SPRING'),
(3,101,'2025-04-01','cancelled','web',2500,NULL),
(4,103,'2025-04-10','paid','store',0,NULL),
(5,104,'2025-04-15','refunded','app',1800,'SPRING'),
(6,102,'2025-04-20','paid','web',NULL,NULL),
(7,105,'2025-04-30','paid','web',1200,''),
(8,103,'2025-05-01','paid','app',4000,'VIP');
-- 誤り:未記録の金額を0円とみなして平均する
SELECT AVG(COALESCE(amount, 0)) AS avg_null_as_zero FROM orders;
-- 参考:NULLを分母から除く
SELECT AVG(amount) AS avg_ignore_null FROM orders;
前者は1712.5円、後者は約1957.1円です。注文6の金額は「0円」ではなく「記録されていない」だけなので、0として平均に入れると平均が約245円下がります。直し方:COALESCE(…, 0) は「未記録=0」と業務で決めた列にだけ使う。決まっていないときはNULLを無視し、除いた件数を併記する(今回は8件中1件)。
まとめ
- NULLは「値がない・不明」。0(0という値)、空文字(文字のない文字列)とは別物。
- NULLとの比較は不明になり、WHERE は真の行だけを残す。判定は IS NULL/IS NOT NULL。
- 3値論理:偽AND不明=偽、真OR不明=真、NOT不明=不明。
- COUNT(列)、SUM、AVG はNULLを無視する。0に直すのは COALESCE、空文字をNULLに寄せるのは NULLIF。
- NOT IN のリストにNULLが入ると全行が消える。サブクエリで IS NOT NULL を付ける。
用語
- NULL(NULL)
値がないことを表す特別な印。未入力・不明・該当なしを表す。0や空文字とは別物。
- 3値論理(three-valued logic)
真・偽・不明の3つの値で条件を評価する論理。NULLを含む比較は不明になる。
- IS NULL(IS NULL)
値がNULLかどうかを判定する条件。
= NULLは使えない。- COALESCE(COALESCE)
左から見て最初のNULLでない値を返す関数。NULLを代わりの値に置き換えるときに使う。
- NULLIF(NULLIF)
2つの値が等しければNULLを、違えば最初の値を返す関数。空文字をNULLに寄せるときに使う。
よくある質問
NULLと空文字は同じ扱いにしてよいですか?
業務の意味で決めます。画面の入力欄の空送信が空文字になる設計なら、空文字は「入力なし」でNULLと同じ扱いにするのが自然です。ただし、機械的に同一視せず、NULLIF(列, '') で明示的に寄せてから集計しましょう。
NULLを0に置き換えると、何が問題ですか?
「不明」を「0だった」と書き換えることになり、平均・割合・合計が実際とずれます。無料(0円)と未記録(不明)が区別できなくなるのも問題です。0にするのは、業務で決めた列だけにします。
NULLのある列に NOT NULL 制約を付ければ解決しますか?
制約は将来の入力を防ぎますが、すでに入っているNULLの意味は消えません。また「該当なし」を表すNULLが必要な列もあります。まず列ごとにNULLの意味を決め、必須か任意かを設計に反映します。
MIN/MAX はNULLをどう扱いますか?
NULLを無視して、NULLでない値の最小・最大を返します。すべてがNULLならNULLです。ただし並べ替え(ORDER BY)ではNULLが先頭か末尾に置かれるので、LIMIT 1 で最小値を求めるのとは結果が異なります。
NULLの割合はどう調べますか?
COUNT(*) - COUNT(列) が欠損の件数、1.0 * (COUNT(*) - COUNT(列)) / COUNT(*) が欠損の割合です。分析の最初に、重要な列の欠損割合を確認する習慣を付けましょう(整数どうしの割り算に注意、型・日付・式)。
仕事で、NULLの扱いを関係者に説明するには?
KPI定義書に『分母は金額が記録されている注文。未記録の注文は件数を併記して除外』のように、扱いと除外件数を書きます。数字だけを渡さず、「8件中1件が未記録」と添えると、誤解や後からの修正を防げます。
確認問題
問1 WHERE amount = NULL はどう動くか。
- ① amount が0の行を返す
- ② amount がNULLの行だけを返す
- ③ 常に不明になり、1行も返さない
- ④ エラーで停止する
解答と解説
正解:③
NULLとの = 比較は不明(UNKNOWN)で、WHERE は真の行だけを残すため、0行になります。
問2 NULL AND 0 の結果はどれか。
- ① 0(偽)
- ② 1(真)
- ③ エラー
- ④ NULL(不明)
解答と解説
正解:①
偽と不明のANDは偽です。片方が偽なら、もう片方が何でも全体は偽に確定します。
問3 amount に NULL が1件ある表で、AVG(amount) はどう計算されるか。
- ① 結果が必ずNULLになる
- ② エラーになる
- ③ NULLを0として分母に含める
- ④ NULLを無視し、NULLでない件数で割る
解答と解説
正解:④
AVG、SUM、MIN、MAX はNULLを無視します。分母はNULLでない行の数です。
問4 customer_id NOT IN (SELECT customer_id FROM flagged) で、flagged にNULLの行が1つある場合、結果はどうなるか。
- ① NULLの行だけが除かれる
- ② どの行も返らない(0行)
- ③ 全行が返る
- ④ エラーになる
解答と解説
正解:②
リストにNULLがあると、NOT IN の判定は真になれず不明になるため、全行が消えます。
問5 COALESCE(NULLIF(coupon_code, ''), 'なし') の働きとして正しいものはどれか。
- ① NULLだけを「なし」に変える
- ② 空文字だけを「なし」に変える
- ③ 全部を「なし」に変える
- ④ 空文字もNULLも「なし」に変える
解答と解説
正解:④
NULLIF が空文字をNULLに変え、COALESCE がNULLを「なし」に変えます。
問6 amount >= 1200 の件数が6、amount < 1200 の件数が1、全体が8件のとき、足りない1件は何か。
- ① 金額が NULL の行
- ② 金額が負の行
- ③ 重複した行
- ④ 金額がちょうど1200の行
解答と解説
正解:①
NULLは大小の比較で不明になり、どちらの条件にも入りません。
次に学ぶこと
次は 型・日付・式 で、型・日付・式を扱います。整数どうしの割り算や、時刻付きの日付の境界など、この授業と同じく「静かに数字がずれる」落とし穴を学びます。
その後、モジュール テーブル・SELECT・条件抽出 の総合テストと自力課題で、NULLの比較・ANDとORの優先度・順序未指定をまとめて確認します。
キャリア学習:データサイエンティスト・機械学習エンジニア・DX推進・研究者を目指す人の学習アプリ。164モジュール・984授業を、ブラウザで動くSQLとPythonの演習で。基礎と各分野の最初のモジュールは無料。全部は2,980円の買い切り。
アプリを無料で開く有料版と無料版の違い