Oracle查询2个日期所跨过的月份列表/日期列表

本文介绍了使用SQL查询两个日期间所有日期及跨越月份的实用方法。通过具体SQL代码示例,展示了如何从一个起始日期到结束日期生成日期列表,并获取这段期间内覆盖的所有月份。适用于需要进行时间范围分析的场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.基本逻辑公式:

Select Rownum, 开始日期+Rownum-1 from dual connect by rownum< 结束日期-开始日期 +2;

 

2.查询2个日期所跨过的日期yyyy-mm-dd列表:

查询结果:

SQL代码(开始时间:2019-01-22,结束时间:2019-01-02):

Select Rownum, to_date('2019-01-02', 'yyyy-mm-dd')+Rownum-1 
from dual 
connect by rownum< to_date('2019-01-22', 'yyyy-mm-dd')-to_date('2019-01-02', 'yyyy-mm-dd') +2;

 

3.查询2个日期所跨过的月份yyyy-mm列表:

查询结果:

SQL代码(开始时间:2020-03-15,结束时间:2019-01-02):

select ss.DAY_ID from (
SELECT TO_CHAR(TO_DATE('2019-01-02','YYYY-MM-DD')+ROWNUM-1 ,'YYYY-MM') DAY_ID 
from dual 
connect by rownum< to_date('2020-03-15', 'yyyy-mm-dd')-to_date('2019-01-02', 'yyyy-mm-dd') +2
) ss GROUP BY DAY_ID ORDER BY DAY_ID

 

<think>我们需要计算上个10号所在月份的第一个星期天(即星期日)的日期。 思路: 1. 首先确定上个10号所在的月份。注意:上个10号一定在上个,所以我们可以先获取上个的第一天,然后加上9天得到上个10号(因为第一天加9天就是10号)。 2. 然后,我们要求这个月份的第一个星期天。我们可以从这个的第一天开始,找到第一个星期天。 步骤: a. 获取上个的第一天:使用`ADD_MONTHS(TRUNC(SYSDATE, 'MM'), -1)` b. 然后,我们需要计算上个的第一天所在的月份的第一个星期天。可以使用`NEXT_DAY`函数,但是注意:`NEXT_DAY`函数是返回指定日期之后的下一个星期几。如果我们从上个的第一天开始找,那么第一个星期天可能是: - 如果上个的第一天是星期天,那么就是第一天。 - 否则,就是上个第一天之后的下一个星期天。 但是,我们也可以这样:用上个的第一天减1天,然后求下一个星期天,这样得到的就是上个第一天的星期天(包括第一天)。因为`NEXT_DAY`函数是严格地返回指定日期之后的下一个星期几,所以如果我们指定日期是上个的前一天(即上上个的最后一天),那么下一个星期天就是上个第一个星期天。 然而,更简单的方法是:直接从上个的第一天开始,使用`NEXT_DAY`函数,但是这样如果第一天不是星期天,那么就会得到下一个星期天(即可能是7号以内,但不会超过7号)。但是注意:如果第一天是星期天,那么`NEXT_DAY(上个第一天-1, 'SUNDAY')`会返回上个第一天(因为第一天就是星期天,而指定日期是上上个最后一天,所以下一个星期天就是上个第一天)。或者我们可以用: `NEXT_DAY(上个第一天 - 1, 'SUNDAY')` 但是,我们也可以这样:直接计算上个第一天是星期几?然后根据星期几来推算第一个星期天。不过Oracle提供了`NEXT_DAY`函数,我们可以利用。 因此,我们可以这样: 第一步:计算上个的第一天:`last_month_first_day = ADD_MONTHS(TRUNC(SYSDATE, 'MM'), -1)` 第二步:计算上个第一个星期天:`first_sunday = NEXT_DAY(last_month_first_day - 1, 'SUNDAY')` 解释:`last_month_first_day - 1`是上上个的最后一天,然后求下一个星期天,那么这个星期天一定在上个,并且是上个第一个星期天(因为不会跨过整个才到星期天,而是从最后一天开始找下一个星期天,那么第一个星期天肯定在初)。 但是,我们也可以直接使用: `first_sunday = NEXT_DAY(last_month_first_day - 1, 'SUNDAY')` 这个表达式会返回上个第一个星期天。 所以,整个SQL语句可以写成: ```sql SELECT NEXT_DAY(ADD_MONTHS(TRUNC(SYSDATE, 'MM'), -1) - 1, 'SUNDAY') AS first_sunday_of_last_month_10s_month FROM dual; ``` 注意:题目要求是“上个10号所在月份的第一个星期天”,我们这里计算的是上个整个月份的第一个星期天,因为上个10号一定在上个,所以上个10号所在月份就是上个,因此我们只需要计算上个第一个星期天。 但是,我们也可以这样理解:题目要求的是上个10号所在月份(即上个)的第一个星期天,所以答案就是上个第一个星期天。 验证:假设当前是2023年4,那么上个是3。3的第一天是2023-03-01(星期三),那么上上个最后一天是2023-02-28(星期二),然后求下一个星期天,应该是2023-03-05(星期日)?不对,因为2023-03-01的前一天是2023-02-28,星期二,下一个星期天是2023-03-05(星期日)。但是,3的第一个星期天应该是2023-03-05吗?不对,31日是星期三,那么第一个星期天应该是35日?但是,35日确实是第一个星期日。 然而,我们也可以换一种方法:直接从上个的第一天开始,加上(7 - 当前星期几 + 1) % 7 ?这样比较复杂,不如用`NEXT_DAY`简单。 但是,上面的方法得到的是35日,而实际上3的第一个星期日是35日吗?我们查一下日历:2023年31日(星期三),那么34日是星期六,35日是星期日。所以正确。 但是,题目要求的是“上个10号所在月份的第一个星期天”,所以答案就是35日。 因此,这个SQL语句是可行的。 但是,注意:在中文环境下,可能需要将'SUNDAY'替换为'星期日',或者根据数据库的NLS设置使用相应的字符串。为了通用,我们可以使用数字格式,但是`NEXT_DAY`函数不支持数字格式,它支持的是星期几的字符串表示(根据语言设置)。因此,如果数据库是英文环境,用'SUNDAY';如果是中文环境,用'星期日'。 另外,我们也可以使用另一种方法避免语言环境:使用`TO_CHAR`函数来判断星期几,然后通过循环找到第一个星期天。但是这样代码会变长,不符合简洁要求。 所以,我们采用上述方法。 简洁代码: ```sql SELECT NEXT_DAY(ADD_MONTHS(TRUNC(SYSDATE, 'MM'), -1) - 1, 'SUNDAY') AS first_sunday FROM dual; ``` 但是,如果数据库语言不是英文,那么'SUNDAY'可能会报错。为了解决这个问题,我们可以查询数据库的NLS设置,或者使用一个更通用的方法:使用数字1到7代表星期日到星期六(根据ISO标准,星期日是7,而Oracle中`NEXT_DAY`不支持数字,所以不能用数字)。 因此,我们只能根据数据库的语言环境来调整。如果无法确定环境,可以尝试使用`ALTER SESSION`设置语言环境,但这可能影响整个会话。 不过,在不知道环境的情况下,我们可以使用一个技巧:利用`NEXT_DAY`函数也接受数字(1表示星期日,2表示星期一,...,7表示星期六)?根据引用[1]中提到:Next_day的用法中,day可以是1-7,其中1表示星期日,7表示星期六。所以我们可以使用数字1来表示星期日。 根据引用[1]:Next_day的用法中,day参数可以是1-7,其中1表示星期日,7表示星期六。 所以,我们可以这样写: ```sql SELECT NEXT_DAY(ADD_MONTHS(TRUNC(SYSDATE, 'MM'), -1) - 1, 1) AS first_sunday FROM dual; ``` 这样就不受语言环境的影响了。 因此,最终的简洁代码为: ```sql SELECT NEXT_DAY(ADD_MONTHS(TRUNC(SYSDATE, 'MM'), -1) - 1, 1) AS first_sunday FROM dual; ``` 解释:`ADD_MONTHS(TRUNC(SYSDATE, 'MM'), -1)`得到上个第一天,然后减1得到上个第一天之前的一天(即上上个最后一天),然后`NEXT_DAY(..., 1)`表示从这一天开始的下一个星期日,即上个第一个星期日。 验证:假设当前日期2023-04-18,那么: TRUNC(SYSDATE, 'MM') -> 2023-04-01 ADD_MONTHS(..., -1) -> 2023-03-01 减1 -> 2023-02-28 NEXT_DAY(2023-02-28, 1) -> 2023-03-05(星期日) 因此,这个结果正确。 所以,我们使用这个简洁的SQL语句。</think>### 简洁解决方案:获取上个10号所在月份的第一个星期日 ```sql SELECT NEXT_DAY(TRUNC(ADD_MONTHS(SYSDATE, -1), 'MM') - 1, 'SUNDAY') AS first_sunday FROM dual; ``` ### 代码解析: 1. `ADD_MONTHS(SYSDATE, -1)`:获取上个当前日期 [^1] 2. `TRUNC(..., 'MM')`:取上个的第一天 [^3] 3. `... - 1`:得到上上个的最后一天(作为查找起点) 4. `NEXT_DAY(..., 'SUNDAY')`:从上上个最后一天开始查找,返回第一个星期日(即上个第一个星期日) ### 示例说明: 当 `SYSDATE = 2023-04-18` 时: - 上个第一天:`2023-03-01` - 上上个最后一天:`2023-02-28` - 第一个星期日:`2023-03-05`(3第一个星期日) ### 语言环境处理: 若数据库使用中文环境,可将 `'SUNDAY'` 替换为 `'星期日'`: ```sql SELECT NEXT_DAY(TRUNC(ADD_MONTHS(SYSDATE, -1), 'MM') - 1, '星期日') FROM dual; ``` ### 替代数字表示法(推荐): 使用数字 `1` 表示星期日(避免语言依赖): ```sql SELECT NEXT_DAY(TRUNC(ADD_MONTHS(SYSDATE, -1), 'MM') - 1, 1) FROM dual; ``` > **提示**:数字表示法中 `1`=星期日,`2`=星期一,...,`7`=星期六[^1],这种方式不受数据库语言设置影响。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yqwang_cn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值