MySQL:有条件地对时间序列进行分组

问题描述 投票:0回答:1

我正在尝试根据日期总数提供按日期、周或月分组的时间序列总和。例如,如果最多 30 天,则按日期分组;如果在 31 到 90 天之间,则按周分组;如果超过 90 天,则按月分组。

我已经通过以下查询得到了我需要的结果:

  1. 按日期分组:
SELECT
    dtCreated,
    FROM_DAYS(TO_DAYS(dtCreated) -MOD(TO_DAYS(dtCreated) -1, 7)) as week_beginning,
    DATE(DATE_FORMAT(dtCreated, '%Y-%m-01')) AS month_beginning,
    COALESCE(SUM(valToSum), 0) as soma
    FROM(   
        SELECT 
            DATE(dt_created) as dtCreated,
            valToSum
        FROM MQV_PDV_TICKET
    ) as derived_table
GROUP BY dtCreated
  1. 按周分组:
SELECT
    dtCreated,
    FROM_DAYS(TO_DAYS(dtCreated) -MOD(TO_DAYS(dtCreated) -1, 7)) as week_beginning,
    DATE(DATE_FORMAT(dtCreated, '%Y-%m-01')) AS month_beginning,
    COALESCE(SUM(valToSum), 0) as soma
    FROM(   
        SELECT 
            DATE(dt_created) as dtCreated,
            valToSum
        FROM MQV_PDV_TICKET
    ) as derived_table
GROUP BY week_beginning
  1. 按月分组:
SELECT
    dtCreated,
    FROM_DAYS(TO_DAYS(dtCreated) -MOD(TO_DAYS(dtCreated) -1, 7)) as week_beginning,
    DATE(DATE_FORMAT(dtCreated, '%Y-%m-01')) AS month_beginning,
    COALESCE(SUM(valToSum), 0) as soma
    FROM(   
        SELECT 
            DATE(dt_created) as dtCreated,
            valToSum
        FROM MQV_PDV_TICKET
    ) as derived_table
GROUP BY month_beginning

所有三个选项都工作得很好,并通过适当的分组为我带来正确的总和结果,但我无法使其动态分组,使其取决于总天数。

我已经尝试在

CASE WHEN
子句中使用
GROUP BY
,以这种方式:

GROUP BY (CASE 
             WHEN COUNT(*) <= 30 THEN dtCreated
             WHEN COUNT(*) BETWEEN 31 AND 90 THEN week_beginning
             WHEN COUNT(*) > 90 THEN month_beginning
         END)

但是它让我出错了:

#1111 - invalid use of group function  (GROUP)

如何实现这种条件分组?

提前谢谢!

mysql conditional-statements
1个回答
0
投票

我会使用WITH语句,在单独的查询中检查记录数,然后根据建议的条件对其进行分组。

WITH DateRange AS (
    SELECT
        MIN(DATE(dt_created)) AS start_date,
        MAX(DATE(dt_created)) AS end_date,
        COUNT(DISTINCT DATE(dt_created)) AS total_days
    FROM MQV_PDV_TICKET
),
PreparedData AS (
    SELECT
        DATE(dt_created) AS dtCreated,
        FROM_DAYS(TO_DAYS(dt_created) - MOD(TO_DAYS(dt_created) - 1, 7)) AS week_beginning,
        DATE_FORMAT(dt_created, '%Y-%m-01') AS month_beginning,
        valToSum
    FROM MQV_PDV_TICKET
)
SELECT
    CASE
        WHEN (SELECT total_days FROM DateRange) <= 30 THEN dtCreated
        WHEN (SELECT total_days FROM DateRange) BETWEEN 31 AND 90 THEN week_beginning
        ELSE month_beginning
    END AS grouping_period,
    COALESCE(SUM(valToSum), 0) AS total_sum
FROM PreparedData
GROUP BY grouping_period;
© www.soinside.com 2019 - 2024. All rights reserved.