SQL 统计一年中有多少个星期一,你想知道一年中有多少个星期一、星期二、星期三等。
SQL 统计一年中有多少个星期一 问题描述
你想知道一年中有多少个星期一、星期二、星期三等。
SQL 统计一年中有多少个星期一 解决方案
为了统计出一年里每个“星期 x”出现的次数,我们必须:
(1) 生成一年里所有可能的日期值;
(2) 格式化上述日期值,并找出它们分别是星期几;
(3) 统计每个“星期 x”出现的次数。
DB2
使用 WITH
递归查询,这样就不需要对一个至少含有 366 行记录的表做 SELECT
查询了。使用 DAYNAME
函数获知每一个日期是星期几,然后统计每个“星期 x”出现的次数。
MySQL
针对 T500
表做 SELECT
查询以产生出足够行数的结果集,每一行记录代表一年中的一个日期。使用 DATE_FORMAT
函数获知每一个日期是星期几,然后统计每个“星期 x”出现的次数。
Oracle
对于 Oracle 9i 及其后续版本,可以使用 CONNECT BY
递归查询返回一年中的每一天。如果是 Oracle 8i 或更早版本,则需要针对 T500
表做 SELECT
查询以产生出足够行数的结果集,每一行记录代表一年中的一个日期。不论哪种方法,都需要使用 TO_CHAR
函数以获知每一个日期是星期几,然后统计每个“星期 x”出现的次数。
首先来看一下 CONNECT BY 解决方案。
其次是针对 Oracle 早期版本的解决方案。
PostgreSQL
使用内置函数 GENERATE_SERIES
为一年中的每一天生成一行记录。然后使用 TO_CHAR
函数获知每一个日期是星期几。最后,统计每个“星期 x”出现的次数。例如:
SQL Server
使用 WITH
递归查询,这样就不需要对一个至少含有 366 行记录的表做 SELECT
查询了。如果是早期不支持 WITH
子句的 SQL Server 版本,参考 Oracle 解决方案里使用数据透视表的做法。使用 DATENAME
函数获知一个日期是星期几,然后统计每个“星期 x”出现的次数。例如:
SQL 统计一年中有多少个星期一 扩展知识
DB2
WITH
递归查询视图 X
里的内嵌视图 TMP
返回当前年份第一天的日期,如下所示。
然后在 START_DATE
基础上加上一年,这样我们就知道了这一年的第一天和最后一天的日期。我们需要知道这两个日期,因为要生成这一年的所有日期。START_DATE
和 END_DATE
如下所示。
下一步是为 START_DATE
加上一天,如此循环往复,直到它等于 END_DATE
。下面展示了 WITH
递归查询视图 X
返回的结果集的一部分。
最后,针对 WITH
递归查询视图 X
的返回结果调用 DAYNAME
函数,并统计每个“星期 x”出现的次数。最终结果如下所示。
MySQL
本解决方案结合 T500
表执行 SELECT
查询,为一年中的每一个日期生成单独的一行数据。第 4 行的命令用于生成当前年份的第一天。它的做法是调用 CURRENT_DATE
函数得到年份,然后在后面附加上月份和天(遵守 MySQL 默认的日期格式)。结果如下所示。
现在有了当前年份第一天的日期,调用 DATEADD
函数将其与 T500.ID
逐一相加以生成一年里的每一天。调用 DATE_FORMAT
函数能够返回每一个日期是星期几。为了以 T500
表为基础生成足够多的行,要先找出当前年份第一天和下一年度第一天之间的差值,并生成与之相等数目的行(应该是 365 行或者 366 行)。部分查询结果如下所示。
现在有了当前年份每一天的日期了,接下来要调用 DAYNAME
函数得到每一个日期是星期几,并统计每个“星期 x”出现的次数。最终结果如下所示。
Oracle
有两种解决方案:结合 T500
表(数据透视表)执行 SELECT
查询,或者使用 CONNECT BY
和 WITH
递归查询,都能为当前年份的每一个日期生成单独的一行数据。使用 TRUNC 函数把当前的系统日期转换为当前年份的第一天。
对于 CONNECT BY
和 WITH
解决方案,我们利用临时的 LEVEL
列生成从 1 开始的数字序列。为了生成足够多行的数据,根据当前年份第一天和下一年度第一天之间的差值(应该是 365 天或者 366 天)筛选 ROWNUM
或者 LEVEL
。下一步就是在当前年份第一天的基础上依次加上 ROWNUM
或者 LEVEL
。部分查询结果如下所示。
对于使用数据透视表的解决方案,我们可以使用任何行数超过 366 行的表或者视图。由于 Oracle 支持 ROWNUM
,我们并不需要一个从 1 开始递增的表。在下面的例子中,我们利用数据透视表 T500
来返回当前年份的每一天。
不论是哪种解决方案,最终我们必须调用 TO_CHAR
函数获取每一个日期分别是星期几,然后统计每个“星期 x”出现的次数。最终结果如下所示。
PostgreSQL
首先调用 DATE_TRUNC
函数获取当前的年份(如下所示,由于针对 T1
做查询,因而只返回一行结果)。
然后,针对一个至少有 366 行的数据源(任何表达式均可)执行 SELECT
查询。本解决方案采用了 GENERATE_SERIES
函数作为数据源。当然,这里也可以用 T500
表。然后,在当前年份第一天的基础上逐次加上 1,直到把一年中的每一天都作为单独的一行返回(如下所示)。
最后,调用 TO_CHAR
函数获取每一个日期分别是星期几,然后统计每个“星期 x”出现的次数。最终的结果如下所示。
SQL Server
WITH
递归查询视图 X
里的内嵌视图 TMP
返回当前年份的第一天,如下所示。
得到当前年份的第一天之后,再为 START_DATE
加上一年,这样我们就知道了开始日期和结束日期。我们需要知道这两个日期,因为需要生成这一年中的每一天。START_DATE
和 END_DATE
如下所示。
下一步,为 START_DATE
加上一天,如此循环往复,直到它等于 END_DATE
。如下展示了 WITH
递归查询视图 X
返回的结果集的一部分。
最后一步是针对 WITH
递归查询视图 X
的返回结果调用 DAYNAME
函数,并统计每个“星期 x”出现的次数。最终结果如下所示。