我的问题是基于具有datetime_value和value结构的表创建查询。 记录是每1小时间隔一个值。 我要实现的目标是创建一个查询,该查询将返回指定时期内按天分组的天数。 例如,我的输入参数是:开始日期,结束日期和类型。 start_date和end_date表示要搜索的日期范围 type表示期间的划分类型:
如果数字在(1,12)范围内,则是特定月份的天数-我设法做到了
如果为空”,则表示一年中的天数-也已完成
如果(第一季度,第二季度,第三季度,第四季度)是指定季度的天数:
-Q1-第6、7、8个月
-Q2-第9、10、11个月
-Q3-第12个月以及从明年起:1、2-最大的问题!
-Q4-第3、4、5个月
例如,当我指定时:
SET @start_date = 2017-12-20 00:00:00
SET @end_date = 2019-04-30 23:59:59
SET @type = 'Q3'
我想接收按期间分组的日期范围内的天数:
period | num_of_days
Q3_17_18 | 71 (dec 2017 from start_date + jan, feb 2018 = 12+31+28)
Q3_18_19 | 90 (dec 2018 + jan, feb 2019 = 31+31+28)
对于其他季度,这很容易-我只使用month(datetime_value)IN(6,7,8)等。但是他的主要问题是Q3,因为它由不同年份的月份组成。 在源表下方:
datetime_value | value |
2018-04-21 00:01:00 | 100 |
2018-04-21 00:02:00 | 400 |
2018-04-21 00:03:00 | 200 |
...
2019-02-03 00:16:00 | 100 |
2018-04-21 00:17:00 | 500 |
答案 0 :(得分:0)
@cornisto,我假设您在有关期间内每天在表中至少有一行。要减少每小时的行并每天获得一行,您可以先:
GROUP BY
YEAR(datetime_value), MONTH(datetime_value), DAY(datetime_value)
要获取以6月为每年的第一个月的年度月份,
((((MONTH(datetime_value) + 7) - 1) % 12) + 1) AS mth_of_yr
注意:要调整到6月1日,我将添加7而不是减去5,以防止向MOD运算符显示负值。因此,假设六月通常是一年中的第6个月,但我们希望成为第1个月,则我们将结果加7,将结果13减去1,然后MOD 12将得出0,然后将结果加1以得出所需的最终结果(月)1.我习惯于使用基于日期的编号而不是基于零的编号。
要获得基于同一六月的月份的季度数字:
(((mth_of_yr - 1) DIV 3) + 1) AS qtr_of_yr
要根据每年的年初(每年6月1日)获取当前年份:
(YEAR(datetime_value) - IF(mth_of_yr > 7, 1, 0))
这将确保第二年的1月至5月属于上一年。
正如我在对问题的评论中所说,我建议您分别执行所有此逻辑并创建日历/日期表。有了这样的表格,您的实际查询(以及使用此六月日历的其他查询)将得到大大简化。
答案 1 :(得分:0)
我通过基于输入参数标记周期来设法以完全不同的方式进行操作。这是我的解决方案:
SET @start_date = '2017-01-01 00:00:00';
SET @end_date = '2019-05-30 23:59:59';
SET @period = 'Q3';
SELECT days_by_period.period AS period1, COUNT(*) AS total_days
FROM
(SELECT
date(datetime_value) AS load_date,
max(the_value) AS max_value,
(CASE
WHEN @period LIKE 'Q%' AND MONTH(datetime_value) IN (6, 7, 8) THEN CONCAT('Q1_', RIGHT(YEAR(datetime_value), 2), '_', RIGHT(YEAR(datetime_value), 2) + 1)
WHEN @period LIKE 'Q%' AND MONTH(datetime_value) IN (9, 10, 11) THEN CONCAT('Q2_', RIGHT(YEAR(datetime_value), 2), '_', RIGHT(YEAR(datetime_value), 2) + 1)
WHEN @period LIKE 'Q%' AND MONTH(datetime_value) = 12 THEN CONCAT('Q3_', RIGHT(YEAR(datetime_value), 2), '_', RIGHT(YEAR(datetime_value), 2) + 1)
WHEN @period LIKE 'Q%' AND MONTH(datetime_value) IN (1, 2) THEN CONCAT('Q3_', RIGHT(YEAR(datetime_value), 2) - 1, '_', RIGHT(YEAR(datetime_value), 2))
WHEN @period LIKE 'Q%' AND MONTH(datetime_value) IN (3, 4, 5) THEN CONCAT('Q4_', RIGHT(YEAR(datetime_value), 2) - 1, '_', RIGHT(YEAR(datetime_value), 2))
WHEN @period = 'YEAR' THEN CONCAT('Y_', RIGHT(YEAR(datetime_value), 2))
ELSE CONCAT(UPPER(DATE_FORMAT(datetime_value, '%b')), '_', RIGHT(YEAR(datetime_value), 2))
END) AS period
FROM test_db.my_table
WHERE datetime_value >= @start_date
AND datetime_value <= @end_date
GROUP BY date(datetime_value)) AS days_by_period
GROUP BY period1