Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Okresy zapytań MySQL i wartość maksymalnego spadku w porównaniu z poprzednią wartością maksymalną

Podejrzewam, że można je nieco zoptymalizować, ale te zapytania powinny dać pożądane wyniki. Dzielą te same pierwsze 3 CTE, które generują diff_max wartość dla każdego data_max . W pierwszym zapytaniu po prostu szukamy zmiany tej wartości (z NULL na wartość lub zmniejszenie wartości) w celu wygenerowania wierszy wyjściowych. Czwarty i piąty CTE drugiego zapytania są podobne do pierwszego zapytania, ale dodajemy RANK do diff_max wartości, więc możemy JOIN minimalna wartość (z powiązaną z nią datą) do date_diff_from i date_diff_to wartości z szóstego CTE (który jest taki sam jak moja odpowiedź na Twoje inne pytanie ).

Pytanie 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

Wyjście:

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

Pytanie 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

Wyjście:

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 na dbfiddle




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Ręcznie określ wartość klucza podstawowego w kolumnie JPA @GeneratedValue

  2. MySQL przy aktualizacji zduplikowanych kluczy + dotknięta liczba wierszy

  3. Jak wyświetlić dopasowanie po porównaniu dwóch tabel?

  4. Błąd hibernacji podczas wykonywania DDL za pośrednictwem instrukcji JDBC

  5. Domyślny czas daty i godziny MySQL z interwałem