如何查询SQL表中过去22个工作日/8个周末的条目数据
精准提取指定数量工作日/周末数据的SQL方案
你之前取不准的核心原因是直接对条目做条数限制,单个自然日可能存在多条业务数据,直接limit会导致凑够22条条目但实际覆盖的工作日数量远少于要求值。正确的实现逻辑是先定位满足数量要求的最早日期边界,再拉取边界之后的所有对应类型数据。
- 核心实现步骤
- 先将
created_on字段截断到日期粒度,去重后基于你已有的dow标识标记工作日/周末属性 - 按日期从新到旧排序,对工作日、周末分别做累计排名
- 找到排名覆盖22个工作日/8个周末的最早日期作为数据拉取的下边界
- 回表查询所有创建时间晚于等于下边界、且日期类型匹配的条目即可
- 先将
示例查询语句
以下写法兼容PostgreSQL、Redshift、BigQuery等主流数仓引擎:
WITH date_rank AS ( SELECT created_on::DATE AS stat_date, -- 按你实际的dow返回值调整判断:示例规则为dow=1到5是工作日(周一到周五),0、6是周末(周六周日) CASE WHEN EXTRACT(DOW FROM created_on) BETWEEN 1 AND 5 THEN 'workday' ELSE 'weekend' END AS day_type, ROW_NUMBER() OVER ( PARTITION BY CASE WHEN EXTRACT(DOW FROM created_on) BETWEEN 1 AND 5 THEN 'workday' ELSE 'weekend' END ORDER BY created_on::DATE DESC ) AS day_seq FROM your_table GROUP BY stat_date, day_type -- 按日期去重,避免单日多条数据干扰天数统计 ), date_boundary AS ( SELECT MIN(CASE WHEN day_type = 'workday' AND day_seq <= 22 THEN stat_date END) AS min_workday_date, MIN(CASE WHEN day_type = 'weekend' AND day_seq <= 8 THEN stat_date END) AS min_weekend_date FROM date_rank ) SELECT t.* FROM your_table t, date_boundary b WHERE -- 取最近22个工作日数据用这个条件 (EXTRACT(DOW FROM t.created_on) BETWEEN 1 AND 5 AND t.created_on::DATE >= b.min_workday_date) -- 要取最近8个周末数据就注释掉上面一行,放开下面这行 -- (EXTRACT(DOW FROM t.created_on) IN (0,6) AND t.created_on::DATE >= b.min_weekend_date) ;
引擎适配说明
- MySQL 适配:将
created_on::DATE替换为DATE(created_on),将EXTRACT(DOW FROM created_on)替换为WEEKDAY(created_on),注意MySQL的WEEKDAY返回值规则为周一=0、周二=1…周日=6,工作日判断调整为WEEKDAY(created_on) BETWEEN 0 AND 4,周末判断调整为WEEKDAY(created_on) IN (5,6)即可。 - 如果需要剔除法定节假日,只需要在
date_rankCTE中关联法定节假日维表,把节假日调整为非工作日标记即可,核心排名、取边界的逻辑不需要改动。
注意:如果存在某段日期整个表都没有数据的情况,这个逻辑会自动跳过无数据的日期,只统计实际存在条目的日期数,符合业务数据提取的常规需求。
内容的提问来源于stack exchange,提问作者Hrishikesh
相关产品推荐
相关产品推荐

