【SQL開発実技編】連載(19):データウェアハウスの時間型操作(上級編) 現在月や年のカレンダーを一つのSQLで印刷するには?月の最初と最後の曜日の日付を決定する方法は?

シリーズ記事ディレクトリ

【SQL開発実技】連載(1):SQLについて絶対に言いたいこと
【SQL開発実技】連載(2):簡単な単一テーブルクエリ
【SQL開発実技】連載(3):SQLに関することsorting
【SQL開発実技】シリーズ(4):実行計画からUNION ALLと空文字列&UNIONとORの注意点を考える
【SQL開発実技】シリーズ(5):IN、EXISTS、実行計画から INNER JOIN 、シナリオを分けて暗記する必要はないオンラインまとめ
【SQL開発実践編】シリーズ(6):実行計画からNOT IN、NOT EXISTS、LEFT JOINの効率を見て、内部と外部の関連付け条件を間違えてはいけない
【SQL開発実技】連載(セブン):重複データ前提で2つのテーブルの差分データと対応するレコード数を比較する方法【SQL開発
】実技】連載(第8回):データ挿入を制限する制約よりも柔軟なデータの挿入方法と、insert文で複数のテーブルを同時に挿入する方法【SQL開発実技】連載(9):
An更新すると、他の列のデータが誤って空に更新されますか? マージ書き換えアップデート!重複データを削除する 5 つの方法を教えてください。
【SQL開発実技】シリーズ(10):文字列の分割、文字列の置換、文字列の出現回数のカウントから始まる
【SQL開発実技】シリーズ(11):いくつかのケースを取り上げて語る translate|regexp_replace| listagg |wmsys.wm_concat|substr|regexp_substr よく使う関数
【SQL開発実技】連載(12):3問(文字列の文字を重複排除した上で文字列をアルファベット順にソートする方法は?どの文字列に数字が含まれているかを識別するには?方法は?)区切られたデータを多値の IN リストに変換するには?)
【SQL開発実技】シリーズ(13):共通の集計関数を議論&()よりもsum()を見て従業員の賃金を積み上げる実行計画【SQL開発実技】シリーズ(14):消費後の残高を計算&累積額を
計算銀行の売上高の合計&各部署の給与上位3名を計算する
【SQL開発実技】シリーズ(十五):最も価値の高い行のデータ情報を探し出し、max/min()の合計を素早く計算する keep ()over()、fisrt_value、last_value、ratio_to_report
【SQL開発実技】シリーズ(16):データウェアハウスでの時間型操作(主)日、月、年、時、分、秒差と時差計算【SQL開発実技
】実技】シリーズ(セブンティーン):データウェアハウスの時間型操作(一次) 2つの日付間の稼働日数を求め、各日付の1週間の出現回数を計算し、現在の記録との差を求めるそして次のレコード 日数
【SQL開発実技】シリーズ(18):データウェアハウスでの時間型操作(上級) INTERVAL、EXTRACTと年がうるう年かどうかの見分け方と週の計算【SQL開発実技編】連載(19)
:データウェアハウスの時間型操作(応用編)で現在の月や年のカレンダーを一つのSQLで印刷する方法は?月の最初と最後の曜日の日付を決定する方法は?
【SQL開発実技】シリーズ(20):データウェアハウスにおける時間型操作(上級編) 四半期の開始時刻と終了時刻の取得と不連続な時間データの数え方【SQL開発実践編】シリーズ(21):データウェアハウスにおける時間型
操作データウェアハウス(上級) 重複する日付範囲を特定し、指定した10分間隔でデータを集計する
【SQL開発実技】シリーズ(22):データウェアハウスのレポートシナリオ ☞ 分析機能の効率は速くなければならないのか Chat 1 実装について話す結果セットのページングとインターレース サンプリングの
【SQL開発実技】連載(23):データウェアハウスレポートシナリオ ☞ データ順列の重複排除方法と最大値・最小値を含むレコードの探し方 再度実行計画を使って、分析機能が苦手
【SQL開発実技】シリーズ(24):データウェアハウスレポートシナリオ☞「行から列」「列から行」をケース実行プランで詳しく解説【SQL開発実技】
シリーズ(25): データウェアハウスのレポートシナリオ ☞ 結果セットの重複データは一度しか表示されず、計算部門の給与差額の効率的な書き方とデータを素早くまとめる方法【SQL開発実技】シリーズ(26):
データ倉庫レポートのシナリオ ☞ 雑談 ROLLUP と UNION ALL がそれぞれグループ合計を行う方法と、どの行が集計の結果行であるかを識別する方法



序文

この記事の主な内容は、時間型操作の高度な操作についてです. これらの操作は、データ ウェアハウスでのより困難な時間操作のケースでもあります: 今月のカレンダーまたは今年のカレンダーを 1 つの SQL で出力する方法? ? ? 年の特定の曜日に属するすべての日付を数える方法? 特定の月の特定の曜日の最初と最後の日付を決定する方法? ? ?
【SQL開発実技】 この連載はブロガーが昔の知識の復習として書いています. やはりSQL開発はデータ分析シナリオにおいて非常に重要で基本的なものです. 面接ではよくSQL開発やチューニング経験について聞かれます. 読み終わったらそう思う.これを書いて連載でも何か得られるし、今後は安心してSQL面接に臨めますよ~。


1. 1 年のうちの特定の曜日に属するすべての日付を決定する

この例では、指定された年のすべての金曜日を返し、以前に紹介した知識を使用して 1 年全体の情報を列挙し、それをフィルター処理するように要求します。

SQL> with t as
  2   (select trunc(sysdate, 'y') + (level - 1) as dy
  3      from dual
  4    connect by level <=
  5               (add_months(trunc(sysdate, 'y'), 12) - trunc(sysdate, 'y')))
  6  select dy, to_char(dy, 'day') as 周五 from t where to_char(dy, 'd') = 6;

DY          周五
----------- ---------------------------------------------------------------------------
2023-1-6    星期五
2023-1-13   星期五
2023-1-20   星期五
2023-1-27   星期五
2023-2-3    星期五
2023-2-10   星期五
2023-2-17   星期五
2023-2-24   星期五
2023-3-3    星期五
2023-3-10   星期五
2023-3-17   星期五
2023-3-24   星期五
2023-3-31   星期五
2023-4-7    星期五
2023-4-14   星期五
2023-4-21   星期五
2023-4-28   星期五
2023-5-5    星期五
2023-5-12   星期五
2023-5-19   星期五
2023-5-26   星期五
2023-6-2    星期五
2023-6-9    星期五
2023-6-16   星期五
2023-6-23   星期五
2023-6-30   星期五
2023-7-7    星期五
2023-7-14   星期五
2023-7-21   星期五
2023-7-28   星期五
2023-8-4    星期五
2023-8-11   星期五
2023-8-18   星期五
2023-8-25   星期五
2023-9-1    星期五
2023-9-8    星期五
2023-9-15   星期五
2023-9-22   星期五
2023-9-29   星期五
2023-10-6   星期五
2023-10-13  星期五
2023-10-20  星期五
2023-10-27  星期五
2023-11-3   星期五
2023-11-10  星期五
2023-11-17  星期五
2023-11-24  星期五
2023-12-1   星期五
2023-12-8   星期五
2023-12-15  星期五
2023-12-22  星期五
2023-12-29  星期五

52 rows selected

この例のポイントは、次to_char(dy, 'd')のようなさまざまなクライアント設定の影響を避けるために、判断に使用することです。

SQL> select to_char(sysdate,'day')as day,to_char(sysdate,'d') as d from dual; 

DAY                                                                         D
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
星期三                                                                      4

SQL> alter session set nls_language=american;

Session altered


SQL> select to_char(sysdate,'day')as day,to_char(sysdate,'d') as d from dual;

DAY                                                                         D
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
wednesday                                                                   4

SQL> 

パラメータ「day」を使用すると、異なる文字セットによって返される結果が異なることがわかりますが、「d」は影響を受けません。

2. 月の最初と最後の曜日の日付を決定する

この例では、今月の最初の月曜日と最後の月曜日を返す必要があります. 前の月と今月の終わりの 7 日前の次の週の月曜日をそれぞれ見つけることができます.

SQL> select next_day(trunc(sysdate,'mm')-1,2) as 第一周周一,
  2  next_day(last_day(trunc(sysdate,'mm'))-7,2) as 最后一周的周一
  3  from dual;

第一周周一  最后一周的周一
----------- -----------
2023-2-6    2023-2-27

3. 今月のカレンダーを作成する

今月のカレンダー情報を出力するためのSQLを書く必要があります.
この要求を見ると少し混乱しますか?
それを達成する方法は?? ?
実際には、指定された月のすべての日付を列挙し、対応する週の情報に変換してから、週に応じて「行と列の変換」を行うことができます. ここで行と列を交換する方法を示します.紹介されていないのでpivot/unpivot、やってcase whenみてください。

SQL> with t as
  2   (select trunc(sysdate, 'mm') + (level - 1) as dy
  3      from dual
  4    connect by level <=
  5               (add_months(trunc(sysdate, 'mm'), 1) - trunc(sysdate, 'mm'))),
  6  t1 as
  7   (select to_char(dy, 'iw') as 所在周,
  8           to_char(dy, 'dd') as 日期,
  9           to_number(to_char(dy, 'd')) 周几
 10      from t)
 11  select max(case 周几
 12               when 2 then
 13                日期
 14             end) 周一,
 15         max(case 周几
 16               when 3 then
 17                日期
 18             end) 周二,
 19         max(case 周几
 20               when 4 then
 21                日期
 22             end) 周三,
 23         max(case 周几
 24               when 5 then
 25                日期
 26             end) 周四,
 27         max(case 周几
 28               when 6 then
 29                日期
 30             end) 周五,
 31         max(case 周几
 32               when 7 then
 33                日期
 34             end) 周六,
 35         max(case 周几
 36               when 1 then
 37                日期
 38             end) 周天
 39    from t1
 40   group by 所在周
 41   order by 所在周;

周一                                                                        周二                                                                        周三                                                                        周四                                                                        周五                                                                        周六                                                                        周天
--------------------------------------------------------------------------- --------------------------------------------------------------------------- --------------------------------------------------------------------------- --------------------------------------------------------------------------- --------------------------------------------------------------------------- --------------------------------------------------------------------------- ---------------------------------------------------------------------------
                                                                                                                                                        01                                                                          02                                                                          03                                                                          04                                                                          05
06                                                                          07                                                                          08                                                                          09                                                                          10                                                                          11                                                                          12
13                                                                          14                                                                          15                                                                          16                                                                          17                                                                          18                                                                          19
20                                                                          21                                                                          22                                                                          23                                                                          24                                                                          25                                                                          26
27                                                                          28                                                                                                                                                                                                                                                                                                                                                                                          

SQL> 

4.年間カレンダー

ひと月のカレンダーの書き方は先ほど紹介しました。
一年中だとしたら?やり方が全然違う!! ! 365日を数えてみてください。
ここに小さな問題があり、53 週目のデータの戻り値がto_char(日期,'iw')間違っていて、最初の週が返されます。

SQL> WITH x AS
  2   (SELECT to_date('2013-12-27', 'yyyy-mm-dd') + (LEVEL - 1) AS d
  3      FROM dual
  4    CONNECT BY LEVEL <= 5)
  5  SELECT d, to_char(d, 'day') AS DAY, to_char(d, 'iw') AS iw FROM x;

D           DAY                                                                         IW
----------- --------------------------------------------------------------------------- ---------------------------------------------------------------------------
2013-12-27  星期五                                                                      52
2013-12-28  星期六                                                                      52
2013-12-29  星期日                                                                      52
2013-12-30  星期一                                                                      01
2013-12-31  星期二                                                                      01

SQL> 

このデータは処理する必要case whenが。

SQL> 
SQL> WITH x AS
  2   (SELECT to_date('2013-12-27', 'yyyy-mm-dd') + (LEVEL - 1) AS d
  3      FROM dual
  4    CONNECT BY LEVEL <= 5),
  5  x1 as
  6   (SELECT d,
  7           to_char(d, 'day') AS DAY,
  8           to_char(d, 'mm') AS mm,
  9           to_char(d, 'iw') AS iw
 10      FROM x)
 11  select d,
 12         day,
 13         mm,
 14         iw,
 15         case
 16           when mm = 12 and iw = '01' then
 17            '53'
 18           else
 19            iw
 20         end as new_iw
 21    from x1;

D           DAY                                                                         MM                                                                          IW                                                                          NEW_IW
----------- --------------------------------------------------------------------------- --------------------------------------------------------------------------- --------------------------------------------------------------------------- ---------------------------------------------------------------------------
2013-12-27  星期五                                                                      12                                                                          52                                                                          52
2013-12-28  星期六                                                                      12                                                                          52                                                                          52
2013-12-29  星期日                                                                      12                                                                          52                                                                          52
2013-12-30  星期一                                                                      12                                                                          01                                                                          53
2013-12-31  星期二                                                                      12                                                                          01                                                                          53

SQL> 

したがって、年次カレンダーは次のようにクエリできます。

SQL> with t as
  2   (select trunc(sysdate, 'y') as 本年年初,
  3           add_months(trunc(sysdate, 'y'), 12) as 下年初
  4      from dual),
  5  t1 as
  6   (select 本年年初 + (level - 1) as 日期
  7      from t
  8    connect by level <= 下年初 - 本年年初),
  9  t2 as
 10   (select 日期,
 11           to_char(日期, 'mm') as 月份,
 12           to_char(日期, 'iw') 所在周,
 13           to_number(to_char(日期, 'd')) as 周几
 14      from t1),
 15  t3 as
 16   (select 日期,
 17           月份,
 18           case
 19             when 月份 = 12 and 所在周 = '01' then
 20              '53'
 21             else
 22              所在周
 23           end as 所在周,
 24           周几
 25      from t2)
 26  select case
 27           when lag(月份) over(order by 所在周) = 月份 then
 28            null
 29           else
 30            月份
 31         end as 月份,
 32         所在周,
 33         max(case 周几
 34               when 2 then
 35                日期
 36             end) 周一,
 37         max(case 周几
 38               when 3 then
 39                日期
 40             end) 周二,
 41         max(case 周几
 42               when 4 then
 43                日期
 44             end) 周三,
 45         max(case 周几
 46               when 5 then
 47                日期
 48             end) 周四,
 49         max(case 周几
 50               when 6 then
 51                日期
 52             end) 周五,
 53         max(case 周几
 54               when 7 then
 55                日期
 56             end) 周六,
 57         max(case 周几
 58               when 1 then
 59                日期
 60             end) 周天
 61    from t3
 62   group by 月份, 所在周
 63   order by 2;

月份                                                                        所在周                                                                      周一        周二        周三        周四        周五        周六        周天
--------------------------------------------------------------------------- --------------------------------------------------------------------------- ----------- ----------- ----------- ----------- ----------- ----------- -----------
01                                                                          01                                                                          2023-1-2    2023-1-3    2023-1-4    2023-1-5    2023-1-6    2023-1-7    2023-1-8
                                                                            02                                                                          2023-1-9    2023-1-10   2023-1-11   2023-1-12   2023-1-13   2023-1-14   2023-1-15
                                                                            03                                                                          2023-1-16   2023-1-17   2023-1-18   2023-1-19   2023-1-20   2023-1-21   2023-1-22
                                                                            04                                                                          2023-1-23   2023-1-24   2023-1-25   2023-1-26   2023-1-27   2023-1-28   2023-1-29
                                                                            05                                                                          2023-1-30   2023-1-31                                                   
02                                                                          05                                                                                                  2023-2-1    2023-2-2    2023-2-3    2023-2-4    2023-2-5
                                                                            06                                                                          2023-2-6    2023-2-7    2023-2-8    2023-2-9    2023-2-10   2023-2-11   2023-2-12
                                                                            07                                                                          2023-2-13   2023-2-14   2023-2-15   2023-2-16   2023-2-17   2023-2-18   2023-2-19
                                                                            08                                                                          2023-2-20   2023-2-21   2023-2-22   2023-2-23   2023-2-24   2023-2-25   2023-2-26
                                                                            09                                                                          2023-2-27   2023-2-28                                                   
03                                                                          09                                                                                                  2023-3-1    2023-3-2    2023-3-3    2023-3-4    2023-3-5
                                                                            10                                                                          2023-3-6    2023-3-7    2023-3-8    2023-3-9    2023-3-10   2023-3-11   2023-3-12
                                                                            11                                                                          2023-3-13   2023-3-14   2023-3-15   2023-3-16   2023-3-17   2023-3-18   2023-3-19
                                                                            12                                                                          2023-3-20   2023-3-21   2023-3-22   2023-3-23   2023-3-24   2023-3-25   2023-3-26
                                                                            13                                                                          2023-3-27   2023-3-28   2023-3-29   2023-3-30   2023-3-31               
04                                                                          13                                                                                                                                      2023-4-1    2023-4-2
                                                                            14                                                                          2023-4-3    2023-4-4    2023-4-5    2023-4-6    2023-4-7    2023-4-8    2023-4-9
                                                                            15                                                                          2023-4-10   2023-4-11   2023-4-12   2023-4-13   2023-4-14   2023-4-15   2023-4-16
                                                                            16                                                                          2023-4-17   2023-4-18   2023-4-19   2023-4-20   2023-4-21   2023-4-22   2023-4-23
                                                                            17                                                                          2023-4-24   2023-4-25   2023-4-26   2023-4-27   2023-4-28   2023-4-29   2023-4-30
05                                                                          18                                                                          2023-5-1    2023-5-2    2023-5-3    2023-5-4    2023-5-5    2023-5-6    2023-5-7
                                                                            19                                                                          2023-5-8    2023-5-9    2023-5-10   2023-5-11   2023-5-12   2023-5-13   2023-5-14
                                                                            20                                                                          2023-5-15   2023-5-16   2023-5-17   2023-5-18   2023-5-19   2023-5-20   2023-5-21
                                                                            21                                                                          2023-5-22   2023-5-23   2023-5-24   2023-5-25   2023-5-26   2023-5-27   2023-5-28
                                                                            22                                                                          2023-5-29   2023-5-30   2023-5-31                                       
06                                                                          22                                                                                                              2023-6-1    2023-6-2    2023-6-3    2023-6-4
                                                                            23                                                                          2023-6-5    2023-6-6    2023-6-7    2023-6-8    2023-6-9    2023-6-10   2023-6-11
                                                                            24                                                                          2023-6-12   2023-6-13   2023-6-14   2023-6-15   2023-6-16   2023-6-17   2023-6-18
                                                                            25                                                                          2023-6-19   2023-6-20   2023-6-21   2023-6-22   2023-6-23   2023-6-24   2023-6-25
                                                                            26                                                                          2023-6-26   2023-6-27   2023-6-28   2023-6-29   2023-6-30               
07                                                                          26                                                                                                                                      2023-7-1    2023-7-2
                                                                            27                                                                          2023-7-3    2023-7-4    2023-7-5    2023-7-6    2023-7-7    2023-7-8    2023-7-9
                                                                            28                                                                          2023-7-10   2023-7-11   2023-7-12   2023-7-13   2023-7-14   2023-7-15   2023-7-16
                                                                            29                                                                          2023-7-17   2023-7-18   2023-7-19   2023-7-20   2023-7-21   2023-7-22   2023-7-23
                                                                            30                                                                          2023-7-24   2023-7-25   2023-7-26   2023-7-27   2023-7-28   2023-7-29   2023-7-30
                                                                            31                                                                          2023-7-31                                                               
08                                                                          31                                                                                      2023-8-1    2023-8-2    2023-8-3    2023-8-4    2023-8-5    2023-8-6
                                                                            32                                                                          2023-8-7    2023-8-8    2023-8-9    2023-8-10   2023-8-11   2023-8-12   2023-8-13
                                                                            33                                                                          2023-8-14   2023-8-15   2023-8-16   2023-8-17   2023-8-18   2023-8-19   2023-8-20
                                                                            34                                                                          2023-8-21   2023-8-22   2023-8-23   2023-8-24   2023-8-25   2023-8-26   2023-8-27
                                                                            35                                                                          2023-8-28   2023-8-29   2023-8-30   2023-8-31                           
09                                                                          35                                                                                                                          2023-9-1    2023-9-2    2023-9-3
                                                                            36                                                                          2023-9-4    2023-9-5    2023-9-6    2023-9-7    2023-9-8    2023-9-9    2023-9-10
                                                                            37                                                                          2023-9-11   2023-9-12   2023-9-13   2023-9-14   2023-9-15   2023-9-16   2023-9-17
                                                                            38                                                                          2023-9-18   2023-9-19   2023-9-20   2023-9-21   2023-9-22   2023-9-23   2023-9-24
                                                                            39                                                                          2023-9-25   2023-9-26   2023-9-27   2023-9-28   2023-9-29   2023-9-30   
10                                                                          39                                                                                                                                                  2023-10-1
                                                                            40                                                                          2023-10-2   2023-10-3   2023-10-4   2023-10-5   2023-10-6   2023-10-7   2023-10-8
                                                                            41                                                                          2023-10-9   2023-10-10  2023-10-11  2023-10-12  2023-10-13  2023-10-14  2023-10-15
                                                                            42                                                                          2023-10-16  2023-10-17  2023-10-18  2023-10-19  2023-10-20  2023-10-21  2023-10-22
                                                                            43                                                                          2023-10-23  2023-10-24  2023-10-25  2023-10-26  2023-10-27  2023-10-28  2023-10-29
                                                                            44                                                                          2023-10-30  2023-10-31                                                  
11                                                                          44                                                                                                  2023-11-1   2023-11-2   2023-11-3   2023-11-4   2023-11-5
                                                                            45                                                                          2023-11-6   2023-11-7   2023-11-8   2023-11-9   2023-11-10  2023-11-11  2023-11-12
                                                                            46                                                                          2023-11-13  2023-11-14  2023-11-15  2023-11-16  2023-11-17  2023-11-18  2023-11-19
                                                                            47                                                                          2023-11-20  2023-11-21  2023-11-22  2023-11-23  2023-11-24  2023-11-25  2023-11-26
                                                                            48                                                                          2023-11-27  2023-11-28  2023-11-29  2023-11-30                          
12                                                                          48                                                                                                                          2023-12-1   2023-12-2   2023-12-3
                                                                            49                                                                          2023-12-4   2023-12-5   2023-12-6   2023-12-7   2023-12-8   2023-12-9   2023-12-10
                                                                            50                                                                          2023-12-11  2023-12-12  2023-12-13  2023-12-14  2023-12-15  2023-12-16  2023-12-17
                                                                            51                                                                          2023-12-18  2023-12-19  2023-12-20  2023-12-21  2023-12-22  2023-12-23  2023-12-24
01                                                                          52                                                                                                                                                  2023-1-1
12                                                                          52                                                                          2023-12-25  2023-12-26  2023-12-27  2023-12-28  2023-12-29  2023-12-30  2023-12-31

63 rows selected


SQL> 

この例から、with ステートメントを使用すると、思考とコード表示が非常に明確になり、ステップ t、t1、t2、および t3 が期待された目的を達成したかどうかを簡単に確認できることがわかります。 withステートメントの1つ。


要約する

この章で紹介する4つの時間操作のケースはまだ難しいですが、このレベルに達することができれば、時間タイプの操作は簡単に仕事をすることができるはずです〜

おすすめ

転載: blog.csdn.net/qq_28356739/article/details/129052200