sql >> データベース >  >> RDS >> Mysql

MySQLクエリの期間と最大ドロップの値と先行する最大値

    ある程度最適化できると思いますが、これらのクエリで希望する結果が得られるはずです。これらは、diff_maxを生成する同じ最初の3つのCTEを共有します 各data_maxの値 。最初のクエリでは、その値の変更を探します(NULLから) 出力行を生成するために、値に、または値の減少)。 2番目のクエリの4番目と5番目のCTEは最初のクエリと似ていますが、RANKを追加します。 diff_maxに 値なので、JOIN date_diff_fromの最小値(関連付けられた日付を含む) およびdate_diff_to 6番目のCTEからの値(これは、その他の質問

    質問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
    

    出力:

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

    質問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
    

    出力:

    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
    

    dbfiddleのデモ




    1. プラグイン「FEDERATED」が無効になっています

    2. MySQLでのクエリキャッシュの防止

    3. PHP-MySQLフィールド値によるフィルタリング

    4. に近いテーブル名を解決できません