You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQL如何查找上一年最接近的同星期日期?含同月限制需求

SQL查找上一年最接近指定日期的同星期几

一、通用场景:找上一年最接近的同星期几日期

核心思路是生成上一年中目标日期前后的两个同星期几候选日期,再筛选出与原日期间隔最小的那个。

SQL Server 示例代码

DECLARE @target_date DATE = '2023-06-17';
DECLARE @target_dow INT = DATEPART(dw, @target_date);
DECLARE @prev_year_base DATE = DATEADD(YEAR, -1, @target_date);

-- 生成两个候选同星期几日期
WITH candidate_dates AS (
    SELECT 
        DATEADD(DAY, (@target_dow - DATEPART(dw, @prev_year_base)) % 7, @prev_year_base) AS candidate
    UNION ALL
    SELECT 
        DATEADD(DAY, (@target_dow - DATEPART(dw, @prev_year_base)) % 7 - 7, @prev_year_base) AS candidate
)
-- 筛选上一年日期并按间隔排序取最近
SELECT TOP 1 candidate AS closest_same_dow_date
FROM candidate_dates
WHERE candidate >= DATEADD(YEAR, -1, DATEFROMPARTS(YEAR(@target_date), 1, 1))
  AND candidate < DATEFROMPARTS(YEAR(@target_date), 1, 1)
ORDER BY ABS(DATEDIFF(DAY, @target_date, candidate)) ASC;

MySQL 示例代码

SET @target_date = '2023-06-17';
SET @target_dow = DAYOFWEEK(@target_date);
SET @prev_year_base = DATE_SUB(@target_date, INTERVAL 1 YEAR);

WITH candidate_dates AS (
    SELECT 
        DATE_ADD(@prev_year_base, INTERVAL (@target_dow - DAYOFWEEK(@prev_year_base)) % 7 DAY) AS candidate
    UNION ALL
    SELECT 
        DATE_ADD(@prev_year_base, INTERVAL (@target_dow - DAYOFWEEK(@prev_year_base)) % 7 - 7 DAY) AS candidate
)
SELECT candidate AS closest_same_dow_date
FROM candidate_dates
WHERE candidate >= DATE_FORMAT(DATE_SUB(@target_date, INTERVAL 1 YEAR), '%Y-%m-01')
  AND candidate < DATE_FORMAT(@target_date, '%Y-%m-01')
ORDER BY ABS(DATEDIFF(@target_date, candidate)) ASC
LIMIT 1;

二、限制在同一月份内查找

只需在筛选条件中加入月份匹配的逻辑,确保候选日期属于上一年的同一月份。

SQL Server 示例代码

DECLARE @target_date DATE = '2023-06-17';
DECLARE @target_dow INT = DATEPART(dw, @target_date);
DECLARE @target_month INT = MONTH(@target_date);
DECLARE @prev_year_base DATE = DATEADD(YEAR, -1, @target_date);

WITH candidate_dates AS (
    SELECT 
        DATEADD(DAY, (@target_dow - DATEPART(dw, @prev_year_base)) % 7, @prev_year_base) AS candidate
    UNION ALL
    SELECT 
        DATEADD(DAY, (@target_dow - DATEPART(dw, @prev_year_base)) % 7 - 7, @prev_year_base) AS candidate
)
SELECT TOP 1 candidate AS closest_same_dow_same_month_date
FROM candidate_dates
WHERE candidate >= DATEFROMPARTS(YEAR(@target_date)-1, @target_month, 1)
  AND candidate < DATEFROMPARTS(YEAR(@target_date), @target_month, 1)
ORDER BY ABS(DATEDIFF(DAY, @target_date, candidate)) ASC;

关键注意事项

  • 星期起始差异:不同数据库对星期几的编号规则不同(如SQL Server默认周日=1,MySQL默认周日=1,PostgreSQL默认周一=0),若需统一逻辑,可改用星期名称对比(如DATENAME(dw, date))。
  • 边界情况处理:若上一年同一月份不存在同星期几日期(极端情况),需根据业务需求补充兜底逻辑(如返回NULL或当月最近的其他星期几)。

内容的提问来源于stack exchange,提问作者james

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 22:54:20