テクノロジー

論理削除の絞り込みはWHERE句でやるな

1: ledsun 2025/11/21 19:49

(速度はおいておいて、論理条件だけみたら)parents.deleted_at IS NULL OR children.deleted_at IS NULL で検索したかった話なのかな?

2: punychan 2025/11/21 20:07

parents側の論理削除はここでは無関係だね。LEFT JOINする右側テーブルで論理削除されたレコードをないものとしたければ、JOIN時に条件つけろということ。

3: tatchimee 2025/11/21 20:16

これハマったときあったなあ。理想的には論理削除なしがいいけど、仕方ないときはビュー作るかな。

4: Niemand 2025/11/21 20:25

そもそも、where句の書き方がおかしいだけ。性能はオプティマイザ次第だが論理削除で isnull を使う設計もおかしい。

5: mcq 2025/11/21 20:52

WHERE句っていう文法の問題じゃなくて、子テーブルのフィルタリングとJOIN演算の適用順序を意識する必要がある、という話

6: mak_in 2025/11/21 21:58

個人的には、論理削除のように、毎回必ず同じwhere条件をつけるものは、テーブルを分けるように設計してる。アーキテクトとしては、いつか誰かがやらかす可能性のある設計はできるだけ潰しておきたいところ。

7: n_231 2025/11/21 22:17

具体的なケースの具体的なクエリが無いのでアレだが、where 区でもnot exists ちゃんと書けば済む話では? 論理削除チェックにnull使ってるのも原因か。普通にflagならこんなややこしいことにならない。

8: hdampty7 2025/11/21 22:27

not existsを使うようになって減ったけど、よくやる。よくSQL書いてるときは問題ないんだけど、書いてないと忘れる。

9: turanukimaru 2025/11/21 22:33

LeftJoinだと親があって子がないレコードは見えるけど論理削除した子供を持った親は見えない、という話か。Join条件はできる限りJoinに書く派なのであえて意識したことはなかったな。

10: kumoha683 2025/11/21 22:39

IS NULLでしか論理削除が判定できない データベースの設計がおかしいのでは?

11: lainof 2025/11/21 22:45

Viewを使えみたいな話かと思ったら、そもそも論理削除に限った話じゃなかった。

12: nojimage 2025/11/21 22:53

論理削除は窓から捨てろ。話はそれからだ

13: mohno 2025/11/21 22:56

そりゃ、LEFT JOINなのにchildrenテーブルをparentsの抽出条件に入れちゃダメ、という話なのでは。「不具合」というより仕様というか。「親テーブルの絞り込みはWHERE句で大丈夫です」

14: kadzuya 2025/11/21 23:03

Gemini"「初学者向け:SQLの評価順序におけるハマりどころ」として書き直すべき内容ですね" と言う感じで社内向けには良い注意喚起だけど公開する内容としては技術ブランディング的にマイナスではと心配に…他人事ながら

15: diveintounlimit 2025/11/21 23:04

みんなだいすきゴミ箱機能。

16: soccermono 2025/11/21 23:13

参照以外の作業をする場合、left join 使うのがおかしい

17: Eiichiro 2025/11/21 23:26

どういう場合に子要素が全部削除されてないのに、親要素に削除フラグ立てるのかの利用ケースが思い浮かばない。 子要素がすべて削除もしくは子要素が0の場合削除フラグ立てるのはあり得るけど。

18: shikiarai 2025/11/21 23:41

nullは不定値だ。論理削除はしてるかしてないかなんだからtrue/falseか1/0で判断しろ

19: takeshiketa 2025/11/21 23:43

子テーブルに削除フラグ付けるの正しいの??

20: Kenju 2025/11/22 00:15

ON句で絞り込みをしないでください。ON句はテーブルの接続を表すために使います。 この場合はサブクエリを使うとかですね。というか、消えているはずのデータならビュー作っておけば良くない?

21: labor9 2025/11/22 00:58

なんか当たり前です、みたいに書いてあるけど違和感あんなぁと思ってコメ見て納得。

22: dorapon2000 2025/11/22 01:02

“つまり、子テーブルの論理削除の絞り込みはJOIN句で書いてください。(慣習的にそうしていた人も多いはず)”

23: hiby 2025/11/22 01:06

NULLに意味をもたすな馬鹿たれ、と言う話かと思った。

24: kagehiens 2025/11/22 01:58

ViewとかCTE内で除外してからJoinするとバッチリ安全なので、指導するならそっちじゃない?/削除日付が入っていない事だけが判定基準の論理削除ルールってあまりお勧めしない。何故ならインデックス組みにくいから…。

25: MyFavoriteOne 2025/11/22 02:01

どうでもいいけど"具体的にこんなケースで不具合が"の予約がない商品の抽出ならnot exists使うべきだと思うよ。あと削除日時でチェックせず削除フラグを設けた方が良いよ。

26: Wafer 2025/11/22 02:35

JOIN使ってる時点でアウト

27: pochi-taro00 2025/11/22 02:44

最初にグルーピングでユニークIDを絞った集合のID群を削除するようにした方がええと思うで

28: dodefeg 2025/11/22 03:21

フラグ版だとWHERE (略) AND (children.delete_flag = 0 OR children.id IS NULL)な感じだろうけど同じ結果になるからNULLの問題じゃない / WHEREサブクエリは無謀 / FROMサブクエリ、CTE、VIEWはON絞り込みと大差ない(好みの問題でしかない)

29: FreeCatWork 2025/11/22 03:25

WHERE句はダメにゃ!ボクが優しく教えてあげるにゃ!

30: Fluss_kawa 2025/11/22 03:29

JOIN結果が想像できてないだけでは?最適化がどこまで効くかにもよるけどWITHとかでテーブル細かく作っていけば抜け漏れなく想像しやすくなるよ。たぶん。

31: aktkro 2025/11/22 03:39

理解不能

32: onesplat 2025/11/22 03:50

いろいろ間違ってて草

33: odakaho 2025/11/22 03:56

そもそも親を取りたいのに LEFT JOIN した子を抽出条件にするのが実装ミスくさいってことね。

34: kobito19 2025/11/22 04:47

サブクエリー使う方が自然では。 select * from children where deleted_at is null と left join しろ / " 参照以外の作業をする場合、left join 使うのがおかしい" は何が言いたいのか意味が分からん

35: daichirata 2025/11/22 05:36

主張はわかるけど、評価順とかそういう込み入った話では無い気が。最初のクエリは parent and child になってるんだからそりゃそうだよね感が。

36: mk_55 2025/11/22 05:51

IS NULLってインデックス効かないんじゃなかった?と思ったらちゃんと効くらしい

37: strawberryhunter 2025/11/22 06:18

そもそも論理削除が有り得ない。論理削除のような機能が必要で1つのテーブルで実現するなら、きちんとした業務的な名前が付いた列で表現して普通にWHERE句だろ。シンプルにしておけよ。

38: otchy210 2025/11/22 06:33

ベスト→論理削除フラグ使わない、ベター→ビューを作って常にそれを使う、だと思ってる。

39: ultrabox 2025/11/22 07:05

その昔、Oracleでは外部結合を(+)って書いてた時期があってぇ

40: soulfulmiddleagedman 2025/11/22 07:07

DB

41: queeuq 2025/11/22 07:08

要件変わっとるやんけ。ただのバグだろ

42: knitcapmann 2025/11/22 07:28

論理削除の判定をNULLでやってる仕様がマズい。

43: sailoroji 2025/11/22 07:35

何言ってんだこいつ

44: daishi_n 2025/11/22 07:53

論理削除フラグはNOT NULL定義にするのが基本。カーディナリティが低いとインデックス使わないからこの辺は要検討

45: sabinezu 2025/11/22 07:53

検索結果件数どうすんの。"予約取り消しが論理削除で実装されていた場合、この商品は予約が1件も入っていないのにもかかわらず抽出対象から外れてしまいます"商品検索なのか予約検索なのか仕様がおかしいだけだろ。

46: shoh8 2025/11/22 08:00

ぶっ叩かれてるの、いいね。/こういう時は当事者意識を薄めて、反応の中からスキルアップにつながりそうな文面だけ受け取るのが吉

47: kagerou_ts 2025/11/22 08:09

結合したあとでwhere適用するから実質INNER JOINになるって話かな。たしかにややこい

48: n314 2025/11/22 08:11

論理削除は関係ないような?部署一覧と所属する65才以上の社員一覧、みたいな問いあわせでも同じで、一般的な結合と絞り込みの問題では。

49: runtothehill32 2025/11/22 08:13

ブコメ大半はちゃんと理解されていないなあ。あるあるある。

50: suika3417 2025/11/22 08:22

ソフトデリートにタイムスタンプを入れる系は、 ただのフラグだとユニークが死ぬからだろうな…

51: igrep 2025/11/22 08:39

タイトルが悪い。

52: irh_nishi 2025/11/22 08:46

普通はVIEW作るんじゃないの?そんでselectに書かなきゃ問題ないよね。。。

53: da-yoshi 2025/11/22 09:05

JOINに書くのは結合条件で、WHEREに書くのはデータ全体の取得条件。今回の場合、論理削除された子テーブルをJOIN対象から外すだけの時は結合条件、紐づく親データも対象から外すなら取得条件になる。後者はLEFT JOINと矛盾

54: Iridium 2025/11/22 09:24

ブクマがメチャクチャ割れていて定見がないのがわかる。絶対使うものなんだからDBがシステムとして実装しなよ。

55: soxandcity 2025/11/22 09:38

期待する振る舞いのテストを書くようにすればいいんじゃないかな

56: greenbow 2025/11/22 10:34

SQLの評価順を理解していないと間違えるよ、というだけで論理削除は関係ないのでは。WHERE とJOINどちらの例が正しいかは仕様によるし一般化できる話でもないような

57: hiroshe 2025/11/22 10:34

WHERE使っとるやん、日本語おかしいやろ

58: toro-chan 2025/11/22 10:43

WHERE句以前に、情報技術から言って、親テーブル側で判定したら包含関係が適切じゃない。写像して全件マッチしたら処理が遅くなるに決まってる。それが分からない人は数学から勉強したほうがいい

59: hakushino 2025/11/22 11:43

元記事は言葉の定義がごちゃってるし、そもそものクエリがおかしい。トプコメのようにテーブルを分ける設計が良さそう。その時、削除時に別テーブルへinsertさせるのをアプリ側でやるかDBトリガーを使うかは要件次第か