次の単一ステートメント ソリューションを使用できます。
SELECT a.date date1,
b.date date2,
DATEDIFF(b.date, a.date) ddiff
FROM (
SELECT @a_rn:=@a_rn+1 ascrank,
date
FROM tbl
CROSS JOIN (SELECT @a_rn:=0) var_init
WHERE date BETWEEN '1950-05-01' AND '2012-09-04'
ORDER BY date
) a
JOIN (
SELECT @b_rn:=@b_rn+1 ascrank,
date
FROM tbl
CROSS JOIN (SELECT @b_rn:=-1) var_init
WHERE date BETWEEN '1950-05-01' AND '2012-09-04'
ORDER BY date
) b ON a.ascrank = b.ascrank
ORDER BY ddiff DESC
LIMIT 1
クエリの内訳
この例のデータセットを考えると:
CREATE TABLE tbl (
date DATE
);
INSERT INTO tbl VALUES
('1950-05-01'),
('1965-08-10'),
('1990-12-30'),
('1990-12-29'),
('2012-09-03');
連続する 2 つの日付間の最大の差を見つけたいと考えています (つまり、日付が昇順で並べられている場合、日付とその直前の日付の最大日差を見つけます)。
次の出力が期待されます。
+-------------+------------+--------+
| date1 | date2 | ddiff |
+-------------+------------+--------+
| 1965-08-10 | 1990-12-29 | 9272 |
+-------------+------------+--------+
連続する日付の最大の差は と の間1965-08-10
にあるため1990-12-29
です。
ステップ1:
前の日付と次の日付を並べて取得するために (DATEDIFF
関数を容易にするために) 最初に行うことは、日付の昇順に基づいて各日付にランク番号を付けることです。
日付の順序はそれ自体 (自動インクリメント ID やランク フィールドなどではない) 以外には依存できないため、手動でランクを自分で計算する必要があります。
これは、MySQL 変数を使用して行います。変数を使用するその他のソリューションでは、3 つ以上の個別のステートメントを実行する必要があります。クエリ自体で( を介してCROSS JOIN
)変数を初期化する私の手法は、それを単一のステートメントに含めたままにします。
SELECT @a_rn:=@a_rn+1 ascrank,
date
FROM tbl
CROSS JOIN (SELECT @a_rn:=0) var_init
WHERE date BETWEEN '1950-05-01' AND '2012-09-04'
ORDER BY date
レンダリング:
+----------+------------+
| ascrank | date |
+----------+------------+
| 1 | 1950-05-01 |
| 2 | 1965-08-10 |
| 3 | 1990-12-29 |
| 4 | 1990-12-30 |
| 5 | 2012-09-03 |
+----------+------------+
SQLFiddle デモ
WHERE
日付は指定された 2 つの日付の間になければならないという条件に注意してください。これは、スクリプトから開始日/終了日のパラメーターを挿入する場所です。
ステップ2:
各日付をランク付けしたので、フィールドに基づいて結果のシフト内部結合を実行してascrank
、連続した日付を並べて取得する必要があります。これは、結果を副選択でラップすることによって行います。
派生結果を自己結合する必要があるため、わずかに調整されたパラメーターのみを使用して上記の手順を複製する必要があります。
SELECT *
FROM (
SELECT @a_rn:=@a_rn+1 ascrank,
date
FROM tbl
CROSS JOIN (SELECT @a_rn:=0) var_init
WHERE date BETWEEN '1950-05-01' AND '2012-09-04'
ORDER BY date
) a
JOIN (
SELECT @b_rn:=@b_rn+1 ascrank,
date
FROM tbl
CROSS JOIN (SELECT @b_rn:=-1) var_init
WHERE date BETWEEN '1950-05-01' AND '2012-09-04'
ORDER BY date
) b ON a.ascrank = b.ascrank
レンダリング:
+----------+-------------+----------+------------+
| ascrank | date | ascrank | date |
+----------+-------------+----------+------------+
| 1 | 1950-05-01 | 1 | 1965-08-10 |
| 2 | 1965-08-10 | 2 | 1990-12-29 |
| 3 | 1990-12-29 | 3 | 1990-12-30 |
| 4 | 1990-12-30 | 4 | 2012-09-03 |
+----------+-------------+----------+------------+
SQLFiddle デモ
「わずかに調整されたパラメーター」とは、2 番目のサブセレクトの ascrank 変数 ( ) がではなく@b_rn
から始まるということです。このように、の結合条件は次の日付を昇順で結合します。両方の変数を で初期化したままにしておくこともできますが、 の条件で結合すると、同じ結果が得られます。-1
0
a.ascrank = b.ascrank
0
a.ascrank = b.ascrank-1
でも待って、アスクランクのデートはどうしたの5
?それは注文の最後の日付であるため、それ以降に差を求める日付はありません。そのため、結果の左側に表示する必要はなく、直前の日付と比較するだけで済みます。 .
ステップ 3:
DATEDIFF()
連続した日付が並んだので、2 つの間の日付の差を ( 経由で)取ることができます。
SELECT a.date date1,
b.date date2,
DATEDIFF(b.date, a.date) ddiff
FROM (
SELECT @a_rn:=@a_rn+1 ascrank,
date
FROM tbl
CROSS JOIN (SELECT @a_rn:=0) var_init
WHERE date BETWEEN '1950-05-01' AND '2012-09-04'
ORDER BY date
) a
JOIN (
SELECT @b_rn:=@b_rn+1 ascrank,
date
FROM tbl
CROSS JOIN (SELECT @b_rn:=-1) var_init
WHERE date BETWEEN '1950-05-01' AND '2012-09-04'
ORDER BY date
) b ON a.ascrank = b.ascrank
レンダリング:
+-------------+------------+--------+
| date1 | date2 | ddiff |
+-------------+------------+--------+
| 1950-05-01 | 1965-08-10 | 5580 |
| 1965-08-10 | 1990-12-29 | 9272 |
| 1990-12-29 | 1990-12-30 | 1 |
| 1990-12-30 | 2012-09-03 | 7918 |
+-------------+------------+--------+
SQLFiddle デモ
ステップ 4:
ddiff
これで、最大値を選択するのは簡単です。これは、フィールドでのORDER BY / LIMIT 1
テクニックを使用して行います。ddiff
SELECT a.date date1,
b.date date2,
DATEDIFF(b.date, a.date) ddiff
FROM (
SELECT @a_rn:=@a_rn+1 ascrank,
date
FROM tbl
CROSS JOIN (SELECT @a_rn:=0) var_init
WHERE date BETWEEN '1950-05-01' AND '2012-09-04'
ORDER BY date
) a
JOIN (
SELECT @b_rn:=@b_rn+1 ascrank,
date
FROM tbl
CROSS JOIN (SELECT @b_rn:=-1) var_init
WHERE date BETWEEN '1950-05-01' AND '2012-09-04'
ORDER BY date
) b ON a.ascrank = b.ascrank
ORDER BY ddiff DESC
LIMIT 1
レンダリング:
+-------------+------------+--------+
| date1 | date2 | ddiff |
+-------------+------------+--------+
| 1965-08-10 | 1990-12-29 | 9272 |
+-------------+------------+--------+
最終結果の SQLFiddle デモ
そして、最終結果に到達しました。