Window LAG/ja

From SQLZoo
Language:Project:Language policy English  • 日本語

COVID-19 データ

データに関する注記: このデータは、Rodrigo Pombo が行った作業をもとに、ジョンズ・ホプキンス大学 および 世界保健機関 の情報を基に構築されました。このデータは2020年4月21日に構築されたものであり、このデータセットを最新の状態に保つ計画はありません。

Window関数

SQLのWindow関数には、LAG、LEAD、RANK、NTILEが含まれます。これらの関数は行の「窓(ウィンドウ)」上で動作します。窓とは通常はテーブル内で何らかの意味で隣接する行です。

covid テーブルの紹介

この例ではWHERE節を2020年の3月のイタリア'Italy'の症例を表示するのに使用している

スペインSpainのデータを表示する様に修正する

SELECT name, DAY(whn),
 confirmed, deaths, recovered
 FROM covid
WHERE name = 'Italy'
AND MONTH(whn) = 3 AND YEAR(whn) = 2020
ORDER BY whn
SELECT name, DAY(whn),
 confirmed, deaths, recovered
 FROM covid
WHERE name = 'Spain'
AND MONTH(whn) = 3 AND YEAR(whn) = 2020
ORDER BY whn

LAG関数の紹介

MySQLに関する注意: MariaDBエンジンを使用している場合、https://jira.mariadb.org/browse/MDEV-23866 のバグに遭遇します。 [訳者注 この問題はバージョン 10.11.6-MariaDB-1:10.11.6+maria~ubu2204 で解決済み]

  • 代わりにMicrosoft SQL Serverエンジンを使用できます。
  • 各クエリの前に以下の行を含めることができます:
SET @@sql_mode='ANSI';

LAG関数は、テーブルで前の行のデータを表示するために使用されます。 行を並べる際、データは国名nameによってパーティション分割され、日付whnのデータによって順序付けられます。つまり、イタリアのデータのみが考慮されます。

クエリを修正して、前日の陽性confirmedを表示する。

SELECT name, DAY(whn), confirmed,
   LAG(whn, 1) OVER (PARTITION BY name ORDER BY whn)
 FROM covid
WHERE name = 'Italy'
AND MONTH(whn) = 3 AND YEAR(whn) = 2020
ORDER BY whn
SELECT name, DAY(whn), confirmed,
   LAG(confirmed, 1) OVER (partition by name ORDER BY whn) AS dbf
 FROM covid
WHERE name = 'Italy'
AND MONTH(whn) = 3 AND YEAR(whn) = 2020
ORDER BY whn

LAG(遅延)操作

以下は、前日の症例を示す正しいクエリです:

SELECT name, DAY(whn), confirmed,
   LAG(confirmed, 1) OVER (partition by name ORDER BY whn) AS lag
 FROM covid
WHERE name = 'Italy'
AND MONTH(whn) = 3
ORDER BY whn

LAG列の値が、斜め左上の行の値と一致していることに注意してください。

nameDAY(whn)confirmeddbf
Italy11694null
Italy220361694
Italy325022036
Italy430892502
Italy538583089
Italy646363858
Italy758834636
Italy873755883
Italy991727375
Italy10101499172
...

新規感染者数

確認された症例数は累積値だが、LAGを使用して各日ごとに報告された新規症例数を復元できる。

イタリアItalyの3月における各日の新規症例数を表示する。

SELECT name, DAY(whn), confirmed,
   LAG(confirmed, 1) OVER (PARTITION BY name ORDER BY whn)
 FROM covid
WHERE name = 'Italy'
AND MONTH(whn) = 3 AND YEAR(whn) = 2020
ORDER BY whn
SELECT name, DAY(whn), confirmed -
   LAG(confirmed, 1) OVER (PARTITION BY name ORDER BY whn) as new
 FROM covid
WHERE name = 'Italy'
AND MONTH(whn) = 3 AND YEAR(whn) = 2020
ORDER BY whn

毎週の変化

収集されたデータは推定値でどうしても不正確になる。しかし、より長い間隔をあけることで、その影響をいくらか軽減できる。 データは、WEEKDAY(whn) = 0 で月曜日の数値のみを表示するようにフィルタリングできる。

2020年のイタリアの各週の新規症例数を表示する - 月曜日のみ表示。

SELECT name, DATE_FORMAT(whn,'%Y-%m-%d'), confirmed
 FROM covid
WHERE name = 'Italy'
AND WEEKDAY(whn) = 0 AND YEAR(whn) = 2020
ORDER BY whn
SELECT name,DATE_FORMAT(whn,'%Y-%m-%d'),
  confirmed-LAG(confirmed,1) OVER (ORDER BY whn) "new this week"
  FROM covid
 WHERE name='Italy' and WEEKDAY(whn) = 0 AND YEAR(whn) = 2020

JOINを利用した遅延処理

テーブルを日付演算を使用してJOINすることができる。データが欠落している場合、結果は異なる。


イタリアの各週の新規症例数を表示する - 月曜日のみを表示する。

サンプルクエリでは、DATE_ADD関数を使用して今週(tw)を先週(lw)とJOINする。

SELECT tw.name, DATE_FORMAT(tw.whn,'%Y-%m-%d'), 
 tw.confirmed, lw.confirmed
 FROM covid tw LEFT JOIN covid lw ON 
  DATE_ADD(lw.whn, INTERVAL 1 WEEK) = tw.whn
   AND tw.name=lw.name
WHERE tw.name = 'Italy'
ORDER BY tw.whn
SELECT tw.name, DATE_FORMAT(tw.whn,'%Y-%m-%d'), 
 tw.confirmed - lw.confirmed
 FROM covid tw LEFT JOIN covid lw ON 
  DATE_ADD(lw.whn, INTERVAL 1 WEEK) = tw.whn
   AND tw.name=lw.name
WHERE tw.name = 'Italy'
AND WEEKDAY(tw.whn) = 0
ORDER BY tw.whn

RANK()関数

このクエリは、2020年4月20日における確認された症例数と世界の症例ランキングを表示する。COVIDによる死亡者数も表示される。 米国が最も多く、スペインが2位である… スペインが確認された症例数で2番目に多い一方で、イタリアはウイルスによる死亡者数で2番目に多いことに注意する。

COVIDによる死亡者数のランキングを表示する列を追加する。

SELECT 
   name,
   confirmed,
   RANK() OVER (ORDER BY confirmed DESC) rc,
   deaths
  FROM covid
WHERE whn = '2020-04-20'
ORDER BY confirmed DESC
SELECT 
   name,
   confirmed,
   RANK() OVER (ORDER BY confirmed DESC) rc,
   deaths,
   RANK() OVER (ORDER BY deaths DESC) rc
  FROM covid
WHERE whn = '2020-04-20'
ORDER BY confirmed DESC

感染率

このクエリは、ワールドテーブルをJOINすることで各国の総人口にアクセスし、感染率(10万人あたりの症例数)を計算する。

各国の感染率ランキングを表示する。人口が少なくとも1000万人以上の国のみを含む。

SELECT 
   world.name,
   ROUND(100000*confirmed/population,2)
  FROM covid JOIN world ON covid.name=world.name
WHERE whn = '2020-04-20' AND population > 10000000
ORDER BY population DESC
SELECT 
   world.name,
   ROUND(100000*confirmed/population,2),
   RANK() OVER (ORDER BY 100000*confirmed/population) AS rank
  FROM covid JOIN world ON covid.name=world.name
WHERE whn = '2020-04-20' AND population > 10000000
ORDER BY population DESC

峠を越える

1日あたり少なくとも2万件の新規症例を記録した各国について、国名、新規症例のピーク日、ピーク値を表示する。

SELECT name,DATE_FORMAT(whn,'%Y-%m-%d'),
  newCases AS peakNewCases
FROM (
SELECT name,whn,newCases,
  RANK() OVER 
    (PARTITION BY name ORDER BY newCases DESC) rnc
FROM
(
  SELECT name, whn,
     confirmed -
     LAG(confirmed, 1) OVER
      (PARTITION BY name ORDER BY whn) as newCases
   FROM covid
) AS x
) AS y
WHERE rnc = 1 AND newCases>=20000
ORDER BY name
DataWars, Data Science Practice Projects - LogoDataWars: Practice Data Science/Analysis with +100 Real Life Projects
  • Served by: hammy at 2025-07-03T14:26