sql >> Databáze >  >> RDS >> Mysql

Časová období dotazu MySQL a hodnota maximálního poklesu oproti předchozí maximální hodnotě

Mám podezření, že je lze trochu optimalizovat, ale tyto dotazy by vám měly poskytnout požadované výsledky. Sdílejí stejné první 3 CTE, které generují diff_max hodnotu pro každý data_max . V prvním dotazu pak hledáme změnu této hodnoty (z NULL na hodnotu nebo snížení hodnoty) za účelem generování výstupních řádků. 4. a 5. CTE druhého dotazu jsou podobné prvnímu dotazu, ale přidáváme RANK na diff_max hodnot, takže se můžeme JOIN minimální hodnotu (s přidruženým datem) k date_diff_from a date_diff_to hodnoty od 6. CTE (což je stejné jako moje odpověď na váš jiná otázka ).

Otázka 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

Výstup:

date        diff_max
2017-01-04  -3
2017-01-09  -7
2017-01-11  -10
2017-01-13  -2

Otázka 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

Výstup:

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

Ukázka na dbfiddle




  1. Prováděcí plány Oracle při použití operátoru LIKE s funkcí DETERMINISTIC

  2. Zpracování latence v transakcích MySQL

  3. Proč je maximální časový limit MySQL 838:59:59?

  4. Jak přejmenovat dvě tabulky v jedné atomické operaci v MySQL