Saya menduga mereka agak dapat dioptimalkan tetapi kueri ini akan memberi Anda hasil yang Anda inginkan. Mereka berbagi 3 CTE pertama yang sama yang menghasilkan diff_max
nilai untuk setiap data_max
. Dalam kueri pertama, kami baru saja mencari perubahan dalam nilai itu (dari NULL
ke nilai, atau penurunan nilai) untuk menghasilkan baris output. CTE ke-4 dan ke-5 dari kueri kedua mirip dengan kueri pertama, tetapi kami menambahkan RANK
ke diff_max
nilai, jadi kita bisa JOIN
nilai minimum (dengan tanggal yang terkait) ke date_diff_from
dan date_diff_to
nilai dari CTE ke-6 (yang sama dengan jawaban saya untuk pertanyaan lain
).
Pertanyaan 1:
WITH cte AS (SELECT DATE(`date_time`) AS `date`,
`data`,
MAX(`data`) OVER (ORDER BY `date_time`) AS `data_max`
FROM `test`),
cte2 AS (SELECT `date`,
`data`,
`data_max`,
CASE WHEN `data` < `data_max` THEN `data` - `data_max` END AS `data_diff`
FROM cte),
cte3 AS (SELECT `date`,
MIN(`data_diff`) OVER (PARTITION BY `data_max` ORDER BY `date`) AS `diff_max`
FROM cte2),
cte4 AS (SELECT `date`, `diff_max`, LAG(`diff_max`) OVER (ORDER BY `date`) AS `old_diff_max`
FROM cte3)
SELECT `date`, `diff_max`
FROM cte4
WHERE `diff_max` < `old_diff_max` OR `old_diff_max` IS NULL AND `diff_max` IS NOT NULL
Keluaran:
date diff_max
2017-01-04 -3
2017-01-09 -7
2017-01-11 -10
2017-01-13 -2
Pertanyaan 2:
WITH cte AS (SELECT DATE(`date_time`) AS `date`,
`data`,
MAX(`data`) OVER (ORDER BY `date_time`) AS `data_max`
FROM `test`),
cte2 AS (SELECT `date`,
`data`,
`data_max`,
CASE WHEN `data` < `data_max` THEN `data` - `data_max` END AS `data_diff`
FROM cte),
cte3 AS (SELECT `data_max`, `date`,
MIN(`data_diff`) OVER (PARTITION BY `data_max` ORDER BY date) AS `diff_max`
FROM cte2),
cte4 AS (SELECT `data_max`, `date`, `diff_max`,
LAG(`diff_max`) OVER (ORDER BY `date`) AS `old_diff_max`
FROM cte3),
cte5 AS (SELECT `date`, `diff_max`,
RANK() OVER (PARTITION BY `data_max` ORDER BY `diff_max`) AS `diff_rank`
FROM cte4
WHERE `diff_max` < `old_diff_max` OR `old_diff_max` IS NULL AND `diff_max` IS NOT NULL),
cte6 AS (SELECT `data_max`,
MIN(CASE WHEN `data_diff` IS NOT NULL THEN date END) AS diff_date_from,
MAX(CASE WHEN `data_diff` IS NOT NULL THEN date END) AS diff_date_to
FROM cte2
GROUP BY `data_max`
HAVING diff_date_from IS NOT NULL)
SELECT diff_date_from, diff_date_to, `date` AS diff_max_date, `diff_max`
FROM cte6
JOIN cte5 ON cte5.date BETWEEN cte6.diff_date_from AND cte6.diff_date_to
WHERE cte5.diff_rank = 1
Keluaran:
diff_date_from diff_date_to diff_max_date diff_max
2017-01-04 2017-01-06 2017-01-04 -3
2017-01-09 2017-01-11 2017-01-11 -10
2017-01-13 2017-01-13 2017-01-13 -2