SQL(MySQL)查询在多个时间帧上提取聚合

时间:2016-01-31 09:55:24

标签: mysql sql aggregate-functions

假设我有下表my_table:

+----------+------------+------------+
+ key_code + cost_value + cost_date  +
+----------+------------+------------+
+   AAAA   +       1.01 + 2015-01-05 +
+   AAAA   +       4.04 + 2015-01-10 +
+   AAAA   +       3.03 + 2015-01-15 +
+   AAAA   +       2.02 + 2015-01-20 +
+   BBBB   +       5.05 + 2015-01-05 +
+   BBBB   +       8.08 + 2015-01-10 +
+   BBBB   +       7.07 + 2015-01-15 +
+   BBBB   +       6.06 + 2015-01-20 +
+----------+------------+------------+

我可以使用以下查询提取每个key_code的最小和最大cost_values:

SELECT key_code, MIN(cost_value) AS cost_min, MAX(cost_value) AS cost_max 
FROM my_table 
GROUP BY key_code 
ORDER BY key_code;

+----------+----------+----------+
+ key_code + cost_min + cost_max +
+----------+----------+----------+
+   AAAA   +     1.01 +     4.04 +
+   BBBB   +     5.05 +     8.08 +
+----------+----------+----------+

我可以使用以下查询将最近/最大值限制为过去7天内的cost_values(假设今天= 2015-01-21):

SELECT key_code, MIN(cost_value) AS cost_min_07, MAX(cost_value) AS cost_max_07 
FROM my_table 
WHERE cost_date >= (CURDATE() - INTERVAL 7 DAY) 
GROUP BY key_code 
ORDER BY key_code;

+----------+-------------+-------------+
+ key_code + cost_min_07 + cost_max_07 +
+----------+-------------+-------------+
+   AAAA   +        2.02 +        3.03 +
+   BBBB   +        6.06 +        7.07 +
+----------+-------------+-------------+

但是如果我想同时提取前7,14和21天的最小值/最大值呢?我怎样(最有效)产生以下结果?我想我问的是如何对每个MIN()和MAX()对应用不同的WHERE?

+----------+-------------+-------------+-------------+-------------+-------------+-------------+
+ key_code + cost_min_07 + cost_max_07 + cost_min_14 + cost_max_14 + cost_min_21 + cost_max_21 +
+----------+-------------+-------------+-------------+-------------+-------------+-------------+
+   AAAA   +        2.02 +        3.03 +        2.02 +        4.04 +        1.01 +        4.04 +
+   BBBB   +        6.06 +        7.07 +        6.06 +        8.08 +        5.05 +        8.08 +
+----------+-------------+-------------+-------------+-------------+-------------+-------------+

2 个答案:

答案 0 :(得分:2)

使用条件聚合:

SELECT key_code,
       MIN(CASE WHEN cost_date >= CURDATE() - INTERVAL  7 DAY THEN cost_value END) AS cost_min_07,           
       MAX(CASE WHEN cost_date >= CURDATE() - INTERVAL  7 DAY THEN cost_value END) AS cost_max_07, 
       MIN(CASE WHEN cost_date >= CURDATE() - INTERVAL 14 DAY THEN cost_value END) AS cost_min_14,           
       MAX(CASE WHEN cost_date >= CURDATE() - INTERVAL 14 DAY THEN cost_value END) AS cost_max_14, 
       MIN(CASE WHEN cost_date >= CURDATE() - INTERVAL 21 DAY THEN cost_value END) AS cost_min_21,           
       MAX(CASE WHEN cost_date >= CURDATE() - INTERVAL 21 DAY THEN cost_value END) AS cost_max_21 
FROM my_table 
WHERE cost_date >= (CURDATE() - INTERVAL 21 DAY) 
GROUP BY key_code 
ORDER BY key_code;

答案 1 :(得分:1)

您可以按key_code和句点对结果进行分组。为了获得适当的时间段,我们在7的基础上移动日期,假设CURRENT_DATE()是句点结束。尝试下面的查询。 d_min - 期间开始,d_max - 期末,d_diff - 当前日期和期间日期之间的差异。

set @base=7;
set @v=TO_DAYS(CURRENT_DATE());
set @diff=@base-@v%@base-1;
set @vb=FLOOR((@v+@diff)/@base);

SELECT
    FROM_DAYS(t.vb*@base-@diff) AS d_min,
    FROM_DAYS((t.vb+1)*@base-@diff-1) AS d_max,
    FLOOR(@vb-t.vb) AS d_diff,
    t.key_code,
    t.cost_min,
    t.cost_max
FROM (
SELECT
    key_code,
    MIN(cost_value) AS cost_min,
    MAX(cost_value) AS cost_max,
    FLOOR((TO_DAYS(cost_date)+@diff)/@base) as vb
FROM
    my_table
GROUP BY
    key_code, vb
ORDER BY
    vb DESC, key_code
) t;