SQL ウィンドウ関数 (LEAD、LAG) の前後の関数

窓関数

より複雑なサブクエリを実行する必要がある場合、集計関数は非常に面倒なので、ウィンドウ関数を使用してグループ化し、関数クエリを使用できます。ウィンドウ関数は、集計前と集計後のデータの両方を表示でき、基本行の列値と集計後の結果列を同じ行に返すことができます。

一般的なアプリケーション シナリオ:クラス内の生徒の成績の並べ替え

共通のウィンドウ関数
ここに画像の説明を挿入

ウィンドウ関数の基本形

func_name(<parameter>) 
OVER(
[PARTITION BY <part_by_condition>] 
[ORDER BY <order_by_list> ASC|DESC]
[rows between ?? And ??]
)

特定のフィールドの説明については、前回の記事「SQL ウィンドウ関数と集計関数の基本的な使い方」を参照してください。


関数の前後

LEAD関数やLAG関数は主に現在のフィールドの前または次の値をクエリするために使用され、上または下の値にデータがない場合は NULL として表示されます。

  • LEAD: 後方オフセット
  • LAG: 前方オフセット
LAG(<expression>,offset,default_value) 
OVER(
     PARTITION BY expr,
     ORDER BY expr [ASC|DESC]
	)

フィールドの説明

  • 式: オフセットする必要があるフィールド
  • オフセット: オフセット量
  • default_value: 記録ウィンドウを超えた場合のデフォルト値 (0 に設定可能、デフォルトは null)

応用例1:
日付の前後の気温を比較するための天気表
ここに画像の説明を挿入

  • 前日の気温と翌日の気温を取得する
select *,
lead(temperature, 1) over(order by recordDate) as lead_temp,
lag(temperature, 1) over(order by recordDate) as lag_temp
from weather

ここに画像の説明を挿入

  • 前日より気温が高かった日を取得
with a as (       
select *,
lead(temperature, 1) over(order by recordDate) as lead_temp,
lag(temperature, 1) over(order by recordDate) as lag_temp
from weather
)
select * from a 
where lag_temp < temperature

ここに画像の説明を挿入


アプリケーション 2:
連続 5 日間ログインしたユーザーの LeetCode を検索します: 1454。アクティブ ユーザー

ユーザーログインフォーム
ここに画像の説明を挿入

答え:

  1. ユーザーは同じ日に複数回ログインしている可能性があり、ログイン日は 1 つだけ必要なので、重複を排除するには user_id、login_time でグループ化する必要があります。
  2. lead() over() ウィンドウ関数を使用して、4 番目のログイン日を検索します。
  3. datediff を使用して、4 番目の着陸日が現在の日付から 4 日後、つまり 5 日連続であるかどうかを確認します。

lead日数の差を求めます

select user_id, login_time, 
lead(login_time,4) over(partition by user_id order by login_time) as '5次后登录的时间', 
datediff(lead(login_time,4) over(partition by user_id order by login_time), login_time) as '天数差'
from user_login
group by user_id, date(login_time);

次に、上記から5日間連続でログインしているユーザー、つまり「日差」が4のユーザーを探します。

-- 完整代码
with a as(
select user_id, login_time, 
lead(login_time,4) over(partition by user_id order by login_time) as '5次后登录的时间', 
datediff(lead(login_time,4) over(partition by user_id order by login_time), login_time) as date_diff
from user_login
group by user_id, date(login_time)
)
select distinct user_id from a where date_diff = 4;

ここに画像の説明を挿入


ここで使用される 2 つの主な例は次のとおりです。

-- weather表
drop table if exists weather;
create table weather(
    id int,
    recordDate date,
    temperature int
);
insert into weather
values (1,'2015-01-01',10),
       (2,'2015-01-02',25),
       (3,'2015-01-03',20),
       (4,'2015-01-04',30);

-- 用户登录表
drop table if exists user_login;
create table user_login
( 
user_id varchar(100), 
login_time datetime
); 

insert into user_login values 
(1,'2020-11-25 13:21:12'), 
(1,'2020-11-24 13:15:22'), 
(1,'2020-11-24 10:30:15'), 
(1,'2020-11-24 09:18:27'), 
(1,'2020-11-23 07:43:54'), 
(1,'2020-11-10 09:48:36'), 
(1,'2020-11-09 03:30:22'), 
(1,'2020-11-01 15:28:29'), 
(1,'2020-10-31 09:37:45'), 
(2,'2020-11-25 13:54:40'), 
(2,'2020-11-24 13:22:32'), 
(2,'2020-11-23 10:55:52'), 
(2,'2020-11-22 08:56:33'),
(2,'2020-11-22 06:30:09'), 
(2,'2020-11-21 08:33:15'), 
(2,'2020-11-20 05:38:18'), 
(2,'2020-11-19 09:21:42'), 
(2,'2020-11-02 00:19:38'), 
(2,'2020-11-01 09:03:11'), 
(2,'2020-10-31 07:44:55'), 
(2,'2020-10-30 08:56:33'), 
(2,'2020-10-29 09:30:28'); 

参照元:
MySQL8の窓関数
SQL練習問題:5日間連続ログインしているアクティブユーザー

おすすめ

転載: blog.csdn.net/weixin_46599926/article/details/128276307