LoginSignup
4
1

More than 5 years have passed since last update.

可能な限り直近の日付を持つデータをソートしつつ取得する

Posted at

意外と難しい

例表(TIME_TABLE)

TIME_TABLE

room_id event_name start_date end_date
1 おもちゃ見本市 2017/1/10 2017/2/1
1 A社臨時会議室 2017/3/11 2017/3/31
1 D社株主総会 2017/4/20 2017/4/21
2 おもちゃ見本市 2017/1/10 2017/2/1

dateは1時間単位でしか設定されない想定。

例えば部屋を汚した利用者を特定する

過去データしか無いとわかってる場合は容易

SELECT "部屋1を汚したイベント".event_name FROM (
  SELECT *  FROM TIME_TABLE
  WHERE 
    room_id = 1
    AND start_date <= SYSDATE
  ODER BY start_date DESC
) "部屋1を汚したイベント"
WHERE ROWNUM <= 1

例えば部屋が利用不可にされたので前後の利用者を得つつ現刻から未来、今、過去で近い順に並べる

直後の利用者情報が一番ほしいけど現在利用中、過去利用中も後ろに表示させたい的な動作

難しい。オラオラで実装。ベターかはわからない。

SELECT "部屋1利用するイベント".event_name FROM (
  SELECT  
    SIGN(SYSDATE - start_date) as sign_start_flg,/*過去日なら-1 今なら0 未来日なら+1*/
    SIGN(SYSDATE - start_date) as sign_end_flg,
    ABS(SYSDATE - start_date) as abs_start_dt,
    ABS(SYSDATE - start_date) as abs_end_dt,
    TIME_TABLE.* 
  FROM TIME_TABLE
  WHERE 
    room_id = 1
  ORDER BY sign_start_flg ASC, abs_end_dt ASC /*開始日が未来でかつ終了日が現在日から最も近いイベント*/
) "部屋1利用するイベント"
WHERE ROWNUM <= 10
-- AND sign_end_flg > 0 /*未来、使用中の部屋は拾わない*/

ORDER BYにSELECTで指定した4値の与え方でいろいろ使い回せるのが楽というのもある

秘話

例からは想像できない化物SQLのリファクタリング結果で
もともとは4クエリ発行してたやつをプログラム上で加工してたのが遅すぎて、早くしろと言われた奴がUNIONで悪魔融合。
負荷テスト担当して目標性能の1/3だったのでNGだしたら、じゃあお前がなんとかしろ言われ作った苦肉のSQL。
性能60倍ぐらい改善した。

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1