SQL 判断闰年

SQL 判断闰年判断当前年份是否闰年。

SQL 判断闰年 问题描述

判断当前年份是否闰年。

SQL 判断闰年 解决方案

如果你已经有了一段时间的 SQL 编程经验,那么你肯定知道本问题有多种解法。我也尝试过多种解决方案,它们都能给出正确答案,但是本实例提供的方案可能是最为简单的。下面的解决方案仅仅检查 2 月的最后一天:如果有 2 月 29 日,则当前年份是闰年。
DB2
使用 WITH 子句递归查询返回 2 月的每一天,然后调用聚合函数 MAX 确认 2 月的最后一天。

 1  with x (dy,mth)
 2    as (
 3  select dy, month(dy)
 4    from (
 5  select (current_date -
 6           dayofyear(current_date) days +1 days)
 7            +1 months as dy
 8    from t1
 9          ) tmp1
10   union all
11  select dy+1 days, mth
12    from x
13   where month(dy+1 day) = mth
14  )
15  select max(day(dy))
16    from x

Oracle
使用 LAST_DAY 函数找出 2 月的最后一天。

1 select to_char(
2          last_day(add_months(trunc(sysdate,'y'),1)),
3         'DD')
4   from t1

PostgreSQL
使用 GENERATE_SERIES 函数返回 2 月的每一天,然后调用聚合函数 MAX 找出 2 月的最后一天。

 1  select max(to_char(tmp2.dy+x.id,'DD')) as dy
 2    from (
 3  select dy, to_char(dy,'MM') as mth
 4    from (
 5  select cast(cast(
 6              date_trunc('year',current_date) as date)
 7                         + interval '1 month' as date) as dy
 8    from t1
 9          ) tmp1
10          ) tmp2, generate_series (0,29) x(id)
11    where to_char(tmp2.dy+x.id,'MM') = tmp2.mth

MySQL
使用 LAST_DAY 函数找出 2 月的最后一天。

1 select day(
2         last_day(
3         date_add(
4         date_add(
5         date_add(current_date,
6                  interval -dayofyear(current_date) day),
7                  interval 1 day),
8                  interval 1 month))) dy
9   from t1

SQL Server
使用 WITH 递归查询返回 2 月的每一天,然后调用聚合函数 MAX 确认 2 月的最后一天。

 1    with x (dy,mth)
 2      as (
 3  select dy, month(dy)
 4    from (
 5  select dateadd(mm,1,(getdate()-datepart(dy,getdate()))+1) dy
 6    from t1
 7         ) tmp1
 8   union all
 9  select dateadd(dd,1,dy), mth
10    from x
11   where month(dateadd(dd,1,dy)) = mth
12  )
13  select max(day(dy))
14    from x

SQL 判断闰年 扩展知识

DB2
递归视图 X 里的内嵌视图 TMP1 按照下面的步骤返回 2 月的第一天。
(1) 从当前日期开始;
(2) 调用 DAYOFYEAR 函数确认当前日期是当前年份的第几天;
(3) 从当前日期里减去上述步骤算出的那个数字以得到上一年的 12 月 31 日,然后加上 1 天得到当前年份的 1 月 1 日;
(4) 再加上 1 个月得到 2 月 1 日。
上述步骤的运算结果如下所示。

select (current_date -
          dayofyear(current_date) days +1 days) +1 months as dy
  from t1
 
DY
-----------
01-FEB-2005

然后,调用 MONTH 函数找出内嵌视图 TMP1 返回的日期对应的月份。

select dy, month(dy) as mth
  from (
select (current_date -
          dayofyear(current_date) days +1 days) +1 months as dy
  from t1
       ) tmp1
 
DY           MTH
-----------  ---
01-FEB-2005    2

到此为止的结果只是作为生成 2 月的每一天的递归操作的起点。为了获得 2 月的每一天,不断为 DY 加上 1 天,直到月份不再是 2 月为止。该 WITH 计算的部分结果如下所示。

  with x (dy,mth)
    as (
select dy, month(dy)
  from (
select (current_date -
         dayofyear(current_date) days +1 days) +1 months as dy
  from t1
       ) tmp1
 union all
select dy+1 days, mth
  from x
 where month(dy+1 day) = mth
)
select dy,mth
  from x
 
DY           MTH
-----------  ---
01-FEB-2005  2
...
10-FEB-2005  2
...
28-FEB-2005  2

最后,针对 DY 列调用 MAX 函数返回 2 月的最后一天;如果是 29 日的话,则当前年份是闰年。
Oracle
首先,调用 TRUNC 函数找出当前年份的第一天。

select trunc(sysdate,'y')
  from t1
 
DY
-----------
01-JAN-2005

由于 1 月 1 日是一年中的第一天,下一步就是在此基础上加上 1 个月得到 2 月 1 日。

select add_months(trunc(sysdate,'y'),1) dy
  from t1
 
DY
-----------
01-FEB-2005

然后,调用 LAST_DAY 找出 2 月的最后一天。

select last_day(add_months(trunc(sysdate,'y'),1)) dy
  from t1
 
DY
-----------
28-FEB-2005

最后,调用 TO_CHAR 得到 28 或者 29(这一步不是必需的)。
PostgreSQL
首先观察内嵌视图 TMP1 返回的结果。调用 DATE_TRUNC 函数得到当前年份的第一天,并将其转换为 DATE 类型。

select cast(date_trunc('year',current_date) as date) as dy
  from t1
 
DY
-----------
01-JAN-2005

然后,在当前年份第一天的基础上加上 1 个月,得到 2 月的第一天,并转换为 DATE 类型。

select cast(cast(
            date_trunc('year',current_date) as date)
                       + interval '1 month' as date) as dy
  from t1
 
DY
-----------
01-FEB-2005

接着,从内嵌视图 TMP1 里返回 DY,并依据 DY 计算出月份的值。调用 TO_CHAR 函数返回月份的值。

select dy, to_char(dy,'MM') as mth
  from (
 select cast(cast(
             date_trunc('year',current_date) as date)
                        + interval '1 month' as date) as dy
   from t1
        ) tmp1
 
DY           MTH
-----------  ---
01-FEB-2005    2

到此为止的计算结果构成了内嵌视图 TMP2 的结果集。下一步要用到一个非常有用的函数 GENERATE_SERIES 来生成 29 行数据(值从 1 逐一递增到 29)。GENERATE_SERIES 函数返回的每一行(别名为 X)都和内嵌视图 TMP2DY 相加。部分结果如下所示。

select tmp2.dy+x.id as dy, tmp2.mth
  from (
select dy, to_char(dy,'MM') as mth
  from (
select cast(cast(
            date_trunc('year',current_date) as date)
                       + interval '1 month' as date) as dy
  from t1
       ) tmp1
       ) tmp2, generate_series (0,29) x(id)
 where to_char(tmp2.dy+x.id,'MM') = tmp2.mth
 
DY           MTH
-----------  ---
01-FEB-2005  02
...
10-FEB-2005  02
...
28-FEB-2005  02

最后,调用 MAX 函数找出 2 月的最后一天。针对该日期值调用 TO_CHAR 函数将得到 28 或者 29。
MySQL
首先找出当前年份的第一天:先计算出当前日期是当前年份的第几天,用当前日期减去该值,然后再加上 1 天。DATE_ADD 函数能完成这一步。

select date_add(
       date_add(current_date,
                interval -dayofyear(current_date) day),
                interval 1 day) dy
  from t1
 
DY
-----------
01-JAN-2005

接着,再次调用 DATE_ADD 函数在上述计算结果的基础上加上 1 个月。

select date_add(
       date_add(
       date_add(current_date,
                interval -dayofyear(current_date) day),
                interval 1 day),
                interval 1 month) dy
  from t1
 
DY
-----------
01-FEB-2005

现在得到了 2 月 1 日的日期值,接着调用 LAST_DAY 函数找出 2 月的最后一天。

select last_day(
       date_add(
       date_add(
       date_add(current_date,
                interval -dayofyear(current_date) day),
                interval 1 day),
                interval 1 month)) dy
  from t1
 
DY
-----------
28-FEB-2005

最后,调用 DAY 函数返回 28 或者 29(这一步不是必需的)。
SQL Server
该解决方案利用 WITH 递归查询生成 2 月的每一天。第一步先找出 2 月的第一天。为达到此目的,先找出当前年份的第一天:计算出当前日期是当前年份的第几天,用当前日期减去该值,然后再加上 1 天。既然有了当前年份的第一天,调用 DATEADD 函数加上 1 个月,就能得到 2 月的第一天了。

select dateadd(mm,1,(getdate()-datepart(dy,getdate()))+1) dy
  from t1
 
DY
-----------
01-FEB-2005

接着,返回 2 月的第一天,并计算出该日期对应月份的数值形式。

select dy, month(dy) mth
  from (
select dateadd(mm,1,(getdate()-datepart(dy,getdate()))+1) dy
  from t1
       ) tmp1
 
DY           MTH
-----------  ---
01-FEB-2005    2

然后利用 WITH 子句的递归特性,不断为内嵌视图 TMP1 返回的 DY 加上 1,直到日期对应的月份不再是 2 月,部分结果如下所示。

  with x (dy,mth)
    as (
select dy, month(dy)
  from (
select dateadd(mm,1,(getdate()-datepart(dy,getdate()))+1) dy
  from t1
       ) tmp1
 union all
select dateadd(dd,1,dy), mth
  from x
 where month(dateadd(dd,1,dy)) = mth
)
select dy,mth from x
 
DY           MTH
-----------  ---
01-FEB-2005   02
...
10-FEB-2005   02
...
28-FEB-2005   02

现在得到了 2 月的每一天,最后调用 MAX 函数看一下最后一天是 28 日还是 29 日。还可以调用 DAY 函数返回数字 28 或者 29,而不是一个日期值;不过,这一步不是必需的。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程