是否有更有效的方法来编写 SQL 以按日期和列值对计数进行分组
Is there a more efficient way to write SQL to group counts by date and column value
我定期将状态值 -1 或 1 存储在 H2
数据库中,我需要计算过去 12 个月中按月存储了多少个 -1 和 1。以下代码有效,但我将在多个地方将其用作派生 table,并且想知道是否有更有效的方法。
SELECT STATUS_CODE AS STATUS,
COUNT(*) AS STATUS_COUNT,
CASE
WHEN EXTRACT(EPOCH FROM DATEADD(MONTH,-1,CURRENT_DATE)) < EXTRACT(EPOCH FROM LOG_ENTRY_TIME) THEN 'MONTH 1'
WHEN EXTRACT(EPOCH FROM DATEADD(MONTH,-2,CURRENT_DATE)) < EXTRACT(EPOCH FROM LOG_ENTRY_TIME) THEN 'MONTH 2'
WHEN EXTRACT(EPOCH FROM DATEADD(MONTH,-3,CURRENT_DATE)) < EXTRACT(EPOCH FROM LOG_ENTRY_TIME) THEN 'MONTH 3'
WHEN EXTRACT(EPOCH FROM DATEADD(MONTH,-4,CURRENT_DATE)) < EXTRACT(EPOCH FROM LOG_ENTRY_TIME) THEN 'MONTH 4'
WHEN EXTRACT(EPOCH FROM DATEADD(MONTH,-5,CURRENT_DATE)) < EXTRACT(EPOCH FROM LOG_ENTRY_TIME) THEN 'MONTH 5'
WHEN EXTRACT(EPOCH FROM DATEADD(MONTH,-6,CURRENT_DATE)) < EXTRACT(EPOCH FROM LOG_ENTRY_TIME) THEN 'MONTH 6'
WHEN EXTRACT(EPOCH FROM DATEADD(MONTH,-7,CURRENT_DATE)) < EXTRACT(EPOCH FROM LOG_ENTRY_TIME) THEN 'MONTH 7'
WHEN EXTRACT(EPOCH FROM DATEADD(MONTH,-8,CURRENT_DATE)) < EXTRACT(EPOCH FROM LOG_ENTRY_TIME) THEN 'MONTH 8'
WHEN EXTRACT(EPOCH FROM DATEADD(MONTH,-9,CURRENT_DATE)) < EXTRACT(EPOCH FROM LOG_ENTRY_TIME) THEN 'MONTH 9'
WHEN EXTRACT(EPOCH FROM DATEADD(MONTH,-10,CURRENT_DATE)) < EXTRACT(EPOCH FROM LOG_ENTRY_TIME) THEN 'MONTH 10'
WHEN EXTRACT(EPOCH FROM DATEADD(MONTH,-11,CURRENT_DATE)) < EXTRACT(EPOCH FROM LOG_ENTRY_TIME) THEN 'MONTH 11'
WHEN EXTRACT(EPOCH FROM DATEADD(MONTH,-12,CURRENT_DATE)) < EXTRACT(EPOCH FROM LOG_ENTRY_TIME) THEN 'MONTH 12'
ELSE 'DONE'
END AS WEEK_RANGE
FROM MY_TABLE
WHERE EXTRACT(EPOCH FROM DATEADD(MONTH,-12,CURRENT_DATE)) < EXTRACT(EPOCH FROM LOG_ENTRY_TIME)
GROUP BY STATUS_CODE, WEEK_RANGE
order by week_range
运行 前面代码的结果。
您可以使用 DATEDIFF()
动态计算 log_entry_time
和当前日期之间的差异,以月为单位:
SELECT
status_code AS status,
COUNT(*) AS status_count,
DATEDIFF(MONTH, log_entry_time, CURRENT_DATE) month_range
FROM MY_TABLE
WHERE log_entry_time >= DATEADD(MONTH, -12, CURRENT_DATE)
GROUP BY status_code, month_range
ORDER BY month_range
如果 LOG_ENTRY_TIME
是类似于 date
的数据类型,请不要将其转换为纪元进行比较,因为这样做会阻止在该列上使用索引。您可以改为进行日期比较,如上述查询的 WHERE
子句所示。
这样的东西会更有用吗?
SELECT STATUS_CODE AS STATUS,
COUNT(*) AS STATUS_COUNT,
EXTRACT(YEAR FROM LOG_ENTRY_TIME) || '-' || EXTRACT(MONTH FROM LOG_ENTRY_TIME)
FROM MY_TABLE
WHERE EXTRACT(EPOCH FROM DATEADD(MONTH,-12,CURRENT_DATE)) < EXTRACT(EPOCH FROM LOG_ENTRY_TIME)
GROUP BY STATUS_CODE, WEEK_RANGE
order by week_range;
这与您的查询略有不同,但此查询提供实际月份值(例如“2019-12”)以实现可追溯性,而不是通用 "Month N" 标签。即使不完全是您想要实现的目标,也许这会给出一个想法。
(我不确定 Oracle 的 TRUNC()
的 H2 等价物是什么,但这将有助于收集整月的数据,而不是前一个月的当天;这就是我当时的情况努力实现。)
我定期将状态值 -1 或 1 存储在 H2
数据库中,我需要计算过去 12 个月中按月存储了多少个 -1 和 1。以下代码有效,但我将在多个地方将其用作派生 table,并且想知道是否有更有效的方法。
SELECT STATUS_CODE AS STATUS,
COUNT(*) AS STATUS_COUNT,
CASE
WHEN EXTRACT(EPOCH FROM DATEADD(MONTH,-1,CURRENT_DATE)) < EXTRACT(EPOCH FROM LOG_ENTRY_TIME) THEN 'MONTH 1'
WHEN EXTRACT(EPOCH FROM DATEADD(MONTH,-2,CURRENT_DATE)) < EXTRACT(EPOCH FROM LOG_ENTRY_TIME) THEN 'MONTH 2'
WHEN EXTRACT(EPOCH FROM DATEADD(MONTH,-3,CURRENT_DATE)) < EXTRACT(EPOCH FROM LOG_ENTRY_TIME) THEN 'MONTH 3'
WHEN EXTRACT(EPOCH FROM DATEADD(MONTH,-4,CURRENT_DATE)) < EXTRACT(EPOCH FROM LOG_ENTRY_TIME) THEN 'MONTH 4'
WHEN EXTRACT(EPOCH FROM DATEADD(MONTH,-5,CURRENT_DATE)) < EXTRACT(EPOCH FROM LOG_ENTRY_TIME) THEN 'MONTH 5'
WHEN EXTRACT(EPOCH FROM DATEADD(MONTH,-6,CURRENT_DATE)) < EXTRACT(EPOCH FROM LOG_ENTRY_TIME) THEN 'MONTH 6'
WHEN EXTRACT(EPOCH FROM DATEADD(MONTH,-7,CURRENT_DATE)) < EXTRACT(EPOCH FROM LOG_ENTRY_TIME) THEN 'MONTH 7'
WHEN EXTRACT(EPOCH FROM DATEADD(MONTH,-8,CURRENT_DATE)) < EXTRACT(EPOCH FROM LOG_ENTRY_TIME) THEN 'MONTH 8'
WHEN EXTRACT(EPOCH FROM DATEADD(MONTH,-9,CURRENT_DATE)) < EXTRACT(EPOCH FROM LOG_ENTRY_TIME) THEN 'MONTH 9'
WHEN EXTRACT(EPOCH FROM DATEADD(MONTH,-10,CURRENT_DATE)) < EXTRACT(EPOCH FROM LOG_ENTRY_TIME) THEN 'MONTH 10'
WHEN EXTRACT(EPOCH FROM DATEADD(MONTH,-11,CURRENT_DATE)) < EXTRACT(EPOCH FROM LOG_ENTRY_TIME) THEN 'MONTH 11'
WHEN EXTRACT(EPOCH FROM DATEADD(MONTH,-12,CURRENT_DATE)) < EXTRACT(EPOCH FROM LOG_ENTRY_TIME) THEN 'MONTH 12'
ELSE 'DONE'
END AS WEEK_RANGE
FROM MY_TABLE
WHERE EXTRACT(EPOCH FROM DATEADD(MONTH,-12,CURRENT_DATE)) < EXTRACT(EPOCH FROM LOG_ENTRY_TIME)
GROUP BY STATUS_CODE, WEEK_RANGE
order by week_range
运行 前面代码的结果。
您可以使用 DATEDIFF()
动态计算 log_entry_time
和当前日期之间的差异,以月为单位:
SELECT
status_code AS status,
COUNT(*) AS status_count,
DATEDIFF(MONTH, log_entry_time, CURRENT_DATE) month_range
FROM MY_TABLE
WHERE log_entry_time >= DATEADD(MONTH, -12, CURRENT_DATE)
GROUP BY status_code, month_range
ORDER BY month_range
如果 LOG_ENTRY_TIME
是类似于 date
的数据类型,请不要将其转换为纪元进行比较,因为这样做会阻止在该列上使用索引。您可以改为进行日期比较,如上述查询的 WHERE
子句所示。
这样的东西会更有用吗?
SELECT STATUS_CODE AS STATUS,
COUNT(*) AS STATUS_COUNT,
EXTRACT(YEAR FROM LOG_ENTRY_TIME) || '-' || EXTRACT(MONTH FROM LOG_ENTRY_TIME)
FROM MY_TABLE
WHERE EXTRACT(EPOCH FROM DATEADD(MONTH,-12,CURRENT_DATE)) < EXTRACT(EPOCH FROM LOG_ENTRY_TIME)
GROUP BY STATUS_CODE, WEEK_RANGE
order by week_range;
这与您的查询略有不同,但此查询提供实际月份值(例如“2019-12”)以实现可追溯性,而不是通用 "Month N" 标签。即使不完全是您想要实现的目标,也许这会给出一个想法。
(我不确定 Oracle 的 TRUNC()
的 H2 等价物是什么,但这将有助于收集整月的数据,而不是前一个月的当天;这就是我当时的情况努力实现。)