sql >> Databasteknik >  >> RDS >> Mysql

MySQL-frågetidsperioder och värdet för maximalt fall jämfört med föregående maxvärde

Jag misstänker att de kan optimeras något men dessa frågor borde ge dig de resultat du vill ha. De delar samma första 3 CTE som genererar diff_max värde för varje data_max . I den första frågan letar vi efter en förändring i det värdet (från NULL till ett värde eller en minskning av värdet) för att generera utdataraderna. Den andra frågans 4:e och 5:e CTE:er liknar den första frågan, men vi lägger till en RANK till diff_max värden, så att vi kan JOIN minimivärdet (med dess associerade datum) till date_diff_from och date_diff_to värden från den 6:e CTE (vilket är detsamma som mitt svar på dina annan fråga ).

Fråga 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

Utdata:

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

Fråga 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

Utdata:

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

Demo på dbfiddle




  1. Att redigera DataGridview och även spara den i en databastabell med c#

  2. Ta bort rad i mysql och tillhörande från mappen

  3. Hur flyttar man kolumner i en MySQL-tabell?

  4. grupp efter månad i unix-tidsstämpelfältet