指定された期間の使われ方によってはもっと違うバリエーションがあるので これも結論はユースケース次第 0377NAME IS NULL2023/07/31(月) 02:21:45.92ID:???>>372 >「検索」や「整理」というのはキーとして用いることを想定しているように思えるが んなわけあるかw 0378NAME IS NULL2023/07/31(月) 07:23:47.10ID:???>>371 そこに期限がないことを示すならNULLが素直だが検索がやや面倒になるので 他に問題が起こらないならば開始日0000終了日9999という手もある。 0379NAME IS NULL2023/07/31(月) 08:08:15.76ID:???>>377 そんな断言できるものなのか? 0380NAME IS NULL2023/07/31(月) 10:36:33.09ID:???>>379 お前のキーの定義ゆるゆる過ぎるやろ そら議論にならんわ 03813712023/07/31(月) 15:18:31.82ID:??? みなさんアドバイスありがとうございます 範囲検索で必ずヒットさせたいので、 開始日(1000-01-01)、終了日(9999-12-31)のようにします そして表示上は「期間指定なし」とします こうすれば余計なカラムを追加せずに目的が実現できそうですね 0382NAME IS NULL2023/07/31(月) 15:32:40.41ID:??? 終了日に9999は使わない方が良いと思う 0383NAME IS NULL2023/07/31(月) 15:38:26.72ID:??? 終了日を指定しなければinfinite future扱いとするのはよくある話だけど 開始日を指定しなければinfinite past扱いとするのは聞いてことがないな 過去に遡らせる必要があることがないから 03843712023/07/31(月) 15:53:50.88ID:??? それではこういうのどうでしょう?(MySQLです)
SELECT *, IF (date_s IS NULL AND date_e IS NULL, 1, 2) AS is_unlimited FROM `posts` HAVING (date_s <= '2023-07-01' AND date_e >= '2023-07-31') OR is_unlimited=1
date_s(開始日)、date_e(終了日)がともにNULLならis_unlimited(無制限)が1にし、 そうでない場合は2にしてから、HAVINGの条件に加えるとか 0385NAME IS NULL2023/07/31(月) 15:59:51.42ID:MTLXqlZG>>381 文字データ型を想定しているなら、開始日は意味のある業務日付にして、設計書に明記しろ。 開始日の西暦1000年は、データを見ても誰も意図がわからない。こういうのは登録ミスなんじゃないのかと、未来、必ず言われる。 03863712023/07/31(月) 16:03:56.83ID:???>>385 なるほど。そこまで考えていませんでした。 じゃ、適当な数値よりもNULLの方がマシですかね。 で、「date_sとdate_eがともにNULLなら期間指定なしとする」」 と設計書に明記すれば迷わない気がします。 0387NAME IS NULL2023/07/31(月) 16:05:18.32ID:MTLXqlZG>>384 開始日と終了日が必要なデータとそうでないデータがあるなら、複数データを同じ入れ物に入れようとしているアンチ正規化のちょっとよろしくない設計なんだが? 03883712023/07/31(月) 16:08:46.81ID:???>>387 ということは、>>371で書いたA案が正しいのですかね? B案という意見も多いので、どっちが良いのかわからなくなります 0389NAME IS NULL2023/07/31(月) 16:39:20.99ID:??? どの程度の件数が格納されるか不明だけど検索項目になるなら自分ならNULLは許可しない DB上の期間指定なしと入力可能な期間指定を明確に決めて設計するかな DB上開始指定なしは0000-01-01、終了指定なしは9999-12-31、入力可能な期間指定は開始は2000-01-01、終了は2999-12-31など 0390NAME IS NULL2023/07/31(月) 16:53:35.14ID:??? 開始指定なしはビジネスロジック上不明またはメンテ期間以前ってことだろ 前者ならNULLでもいいんじゃないか 3値論理の理想としてる設計だろ 0391NAME IS NULL2023/07/31(月) 16:55:12.55ID:??? 検索項目にする場合、NULLだと都合が悪いのかな 0392NAME IS NULL2023/07/31(月) 17:05:41.13ID:??? 開始終了の日付指定無し=両方NULLを設定する 片方だけNULLは都合が悪い=入力時にチェックするで対応 日付範囲指定で抽出=範囲指定で、NULLデータは検索から排除されてる
これで上手く動くと思うけど、ダメなのかな? 0393NAME IS NULL2023/07/31(月) 18:32:11.87ID:???>>392 テーブル上のケースは A 開始:終了 開始~終了 B 開始:NULL 開始~ C NULL:終了 ~終了 D NULL:NULL 期間なし 例えば日付範囲検索で 開始日以降の条件が発生した場合、開始≦条件の開始日 OR 開始 IS NULL 終了日以前の条件が発生した場合、終了≧条件の終了日 OR 終了 IS NULL とそれぞれNULLの考慮が必要になるからNULLを持たないほうがいいんじゃない? というのが自分の考えだわ 後は例えば開始が2023-01-01、終了が2023-12-31となっているデータがある場合に 2022-12-01~2023-03-31って検索した場合、上のデータが対象になるとNULLが混在するデータの場合に 条件も複雑にならないかね? 0394NAME IS NULL2023/07/31(月) 18:34:05.22ID:??? 質問した人が果たしてそこまで要求してたかどうかは、あやしい 0395NAME IS NULL2023/07/31(月) 21:00:40.56ID:??? そういう意味でテーブルに開始・終了日付を持ち、検索時も開始・終了日付を持つ場合を考慮してNULLはないほうがいいと思ってる 0396NAME IS NULL2023/07/31(月) 21:33:37.76ID:??? DBにもよるけど検索時のIndexも効かないし 俺ならNULL使わないかな 3000万件から無期限のデータだけ取り出したい場合とかINDEX効かせないと辛いやろ 0397NAME IS NULL2023/07/31(月) 21:38:44.77ID:??? 3000万件ですか?すごい大規模な案件ですね そういうのを担当する人が果たしてここで質問するか、 大変興味があります 0398NAME IS NULL2023/07/31(月) 21:52:32.04ID:??? ・NULLは駄目 ・1000-01-01〜9999-12-31のような最小、最大値を入れるのも駄目 ・フラグ用のカラムを入れるのも駄目
ならどう設計するのが適切なの? 0399NAME IS NULL2023/07/31(月) 22:06:34.28ID:??? 絶対にどれがダメなんてことはなくてそれぞれメリットデメリットあるからそれを踏まえて判断すればいい。 条件に関わらず「××は絶対ダメ」という奴がいるかもしれないがそういうのはバカだから無視していい。 0400NAME IS NULL2023/07/31(月) 22:08:57.28ID:???>>396 >3000万件から無期限のデータだけ取り出したい場合 なんでそんなことしたいの? 3000万件から他のインデックス使わずに無期限のデータだけ取り出したい場合があるなら 無期限のデータと有期限のデータは根本的に種類が違うんじゃないの? 0401NAME IS NULL2023/07/31(月) 22:19:05.56ID:???>>396 期限有り無しの二値だとインデックスも効きにくいだろ。よっぽど分布が偏ってない限り。 ビットマップインデックスもこの場合はちょっと違うしなあ。 0402NAME IS NULL2023/07/31(月) 22:33:24.14ID:??? 二値しかないんだから、アクセス時間の方がかかる インデックスあまり意味がない 0403NAME IS NULL2023/07/31(月) 22:40:21.82ID:???>>401 インデックスをどうするか以前に 期限の有無が業務上持つ意味をDB設計に反映できてない可能性があるのではという話
よくあるのは通常の単価とキャンペーン単価の管理の違い 前者は開始日(=切替日)しかないが後者は開始日と終了日がある 0404NAME IS NULL2023/07/31(月) 22:56:02.47ID:??? 本人がいないところで仕様を膨らますのは止めよう 0405NAME IS NULL2023/07/31(月) 23:07:24.63ID:???>>396 >DBにもよるけど検索時のIndexも効かないし オラクルだけじゃなくて? 0406NAME IS NULL2023/07/31(月) 23:14:10.03ID:??? オラクルでも今はNULLをIndexされるようにできるみたいね 0407NAME IS NULL2023/07/31(月) 23:16:19.49ID:??? SQLiteは知らないけど SQL Server, MySQL, PostgresはどれもNULLがIndexingされるので Oracleも大丈夫なら検索性能という意味ではあまり困らないような気がする 0408NAME IS NULL2023/08/01(火) 00:07:30.45ID:??? 最近はOracleでもインデックスに含まれるのか知らなかったww勉強不足で申し訳ない
ただBTREE INDEXは魔法じゃないから データ分布とか検索条件次第ですかね 0409NAME IS NULL2023/08/01(火) 08:13:04.34ID:???>>403 そういうキャンペーン単価を管理するときって、別テーブルにするの?
▽商品テーブル ID|商品名|価格|登録日|更新日
▽キャンペーンテーブル ID|商品ID|キャンペーン価格|開始日|終了日
こんな感じ? でもこれだと商品にキャンペーンがあるかわからないような気が 0410NAME IS NULL2023/08/01(火) 09:06:38.95ID:??? 単価関連は標準単価とは別にキャンペーン用の単価を登録するテーブルを用意したりするんじゃない 0411NAME IS NULL2023/08/01(火) 09:39:35.55ID:??? キャンペーンの設計でいつも迷うのが履歴なんだよな キャンペーン終了したからって削除すると、購入履歴がおかしくなるし 0412NAME IS NULL2023/08/01(火) 10:55:49.31ID:??? 削除前提の設計なら履歴に削除するマスタの情報を付与しておけばいいんじゃない でも普通というか使用されたマスタは削除なんてしないのでは 0413NAME IS NULL2023/08/01(火) 11:07:21.76ID:??? 購入履歴は購入した各ユーザーの履歴として保存すれば良い 0414NAME IS NULL2023/08/01(火) 17:37:59.06ID:??? その履歴が何の履歴でどういう目的で残すものなのかを明らかにすれば設計はおのずと決まると思うが。 0415NAME IS NULL2023/08/01(火) 22:27:22.34ID:???>>409 扱う商品や業種にもよるとおもうけど販売単価は頻繁に変更される場合は 商品名とかを管理する商品マスターには実際の販売単価は入れずに別にテーブルを作る さらにそれとは別にキャンペーン用の単価を管理するテーブルを作る (標準販売単価のような商品IDが決まれば一意に決まるような情報なら商品マスター)
適用される単価を割り出すのに2つ以上のテーブルを確認するというのはアプリロジック
>▽商品テーブル >ID|商品名|価格|登録日|更新日 この設計だと価格を変更したい場合に価格を直接上書きするか商品IDを新しくするかしかなくて普通は困ると思う 0416NAME IS NULL2023/08/01(火) 23:26:21.41ID:??? 開始日・終了日の件は SQL標準に組み込まれたtemporal機能のsystem time periodsの実装方法を見ると 終了日だけオープンにしてdatetime型の最大値をセンティネルとして使ってるDBMSが大半のようなので RDBMS固有の特別事情がなければそれがファーストチョイスでいい気がする 0417NAME IS NULL2023/08/02(水) 00:55:16.14ID:???>>415 >>ID|商品名|価格|登録日|更新日 >この設計だと価格を変更したい場合に価格を直接上書きするか商品IDを新しくするかしかなくて普通は困ると思う キャンペーンテーブルのほうに引きずられたけどよく考えたら ID+更新日の複合主キーかそのサロゲートを使えば要件次第では困らないかもね 0418NAME IS NULL2023/08/02(水) 13:16:59.94ID:??? 価格は適用日に応じた世代を持たせたテーブル作ると楽 0419NAME IS NULL2023/08/02(水) 13:32:20.34ID:??? 適用日に応じた世代とかイミフw 0420NAME IS NULL2023/08/02(水) 13:38:56.67ID:??? 実務やってれば分かることなのに 0421NAME IS NULL2023/08/02(水) 14:57:10.42ID:???>>418 それはみんなわかってて 具体的にどういうやり方がいいのかという話だろ 0422NAME IS NULL2023/08/02(水) 16:07:55.30ID:??? 販売管理の実務やってる奴なんて実際いないんだろ いるなら具体例出すだろうしでないのが何よりの証拠 0423NAME IS NULL2023/08/02(水) 16:15:58.25ID:??? 適用日があるなら世代はいらないんじゃねって話かね? 0424NAME IS NULL2023/08/03(木) 09:58:26.73ID:??? そもそも適用時に応じて世代ってなんぞ? 0425NAME IS NULL2023/08/03(木) 10:00:46.36ID:??? ごめん、思い切りミスった 「適用日に応じた世代ってなんぞ?」だったw
価格が変わる毎にテーブル作るのは非効率に感じるし、 SELECTのSQLがどうなるかわからん 0426NAME IS NULL2023/08/03(木) 10:26:49.29ID:??? 世代番号列を作るってことじゃないの? 必要になるシーンが浮かばないけど 0427NAME IS NULL2023/08/03(木) 11:34:09.40ID:??? ある商品Aがある。通常の単価は100円 10/5は特売日なので80円、それとは別に10/11~15は90円 みたいなケースだと 10/1~4 100円 10/5 80円 10/6~10 100円 10/11~15 90円 10/16~ 100円 みたいになるけどそれぞれの期間を世代とかいってるのか100円でないものだけ世代とか言ってるか意味不明なんだよな 単純に適用日で管理といえばいいと思ってる 0428NAME IS NULL2023/08/03(木) 11:50:48.91ID:??? 後者を世代と言ってるなら要件定義ミスの原因になりかねないほど日本語が不自由だし、前者でも後者でもやはりいらない。 0429NAME IS NULL2023/08/03(木) 13:16:26.10ID:??? 価格テーブル作って ID、価格、開始日、終了日 にしたら世代管理にならないか?って思ったら、>>409に書かれてたw
ほんと言うだけ言って具体例出さないよな 0430NAME IS NULL2023/08/03(木) 15:29:58.52ID:dzanpAeV NULLのカラムを検索結果から除外するSQLなら、そもそもインデックススキャンになるSQLならインデックススキャンになるだろw 0431NAME IS NULL2023/08/03(木) 15:33:17.05ID:dzanpAeV だいたい日付の開始日が設定されていないような状態なら、他のステータス項目で判断できるようなデータモデルじゃないと、クソみたいなSQLだらけになる。 0432NAME IS NULL2023/08/03(木) 15:41:34.40ID:???>>428 それ俺の知ってる言葉の意味と違うから要件定義ミスになっちゃうという話にしか聞こえないぞ 一般的な意味とは違っても現場現場で定着してる語義ってあるからな 自分の知ってる意味と違うならそれを明確化させればいいだけ 0433NAME IS NULL2023/08/03(木) 15:43:58.47ID:???>>429 そういうのを「世代」や「世代管理」とは呼ばないというのが >>427-428の言いたいことなんじゃないかな 0434NAME IS NULL2023/08/03(木) 19:07:02.41ID:??? じゃ、その言いたいことを説明すればいいだけじゃん 他の人は例を出してるのになぜ出さない? 0435NAME IS NULL2023/08/03(木) 19:16:30.28ID:??? 言葉の問題とかどうでもいいから今回の価格の話だけすればいいと思うんだよな 0436NAME IS NULL2023/08/03(木) 21:23:42.18ID:???>>418がしょうもないこと言うから脱線したけど、元々の相談者の悩みは解決したんじゃないか 0437NAME IS NULL2023/08/03(木) 21:47:21.74ID:??? 夏休みだとこの程度なんだろうな 0438NAME IS NULL2023/08/03(木) 22:01:59.09ID:??? データベーススペシャリスト試験は国語力が試されるからそんなもんだろう。 問題文に書いてあることを読み落としたり逆に書いてない行間を読んだりしたら解けない。 0439NAME IS NULL2023/08/03(木) 22:12:43.51ID:??? 急にこういう訳わからん事言うのも夏休みだからかなw 0440NAME IS NULL2023/08/03(木) 22:25:05.03ID:??? 実務やってれば分かるって人は理論とか嫌いだしね 0441NAME IS NULL2023/08/03(木) 22:29:26.60ID:??? DBスペシャリストは実践的なDB設計には役立たないんだよ この1週間の一連の流れだけ見てもわかるよね 0442NAME IS NULL2023/08/03(木) 22:37:38.54ID:??? >この1週間の一連の流れだけ見てもわかるよね
KDD爺の「俺が正しい。根拠は言えないけど。」が多かったね。 実務やってりゃ分かる「世代」って結局何だったのか。 0443NAME IS NULL2023/08/03(木) 22:42:51.15ID:???>>440 リレーショナルセオリーだけじゃ主キーさえ選べない 0444NAME IS NULL2023/08/03(木) 22:49:53.56ID:???>>443 そりゃセオリーだけじゃどんなデータを格納するかすら決められないがそういうのとは違う話? 0445NAME IS NULL2023/08/03(木) 23:22:21.06ID:???>>441 >DBスペシャリストは実践的なDB設計には役立たないんだよ
試験受かった人が自分の設計力のなさを自虐しているのならわかるがそうでないならかなり恥ずかしいな。 0446NAME IS NULL2023/08/03(木) 23:25:47.44ID:gShiht3b NULLに何かしらの意味を定義するやつは永久に消えないんだろうな。