SQL 比较特定的日期要素,你想找出哪些员工在同一个月份和同一个工作日入职。例如,一个员工的入职日期是 1988 年 3 月 10 日,星期一;另一个则是 2001 年 3 月 2 日,星期一。那么,由于二者的月份名称和星期值一致,你认为他们两个的入职日期是相匹配的。对于 EMP
表而言,只有 3 个员工符合这种条件。你希望得到的结果集如下所示。
SQL 比较特定的日期要素 问题描述
你想找出哪些员工在同一个月份和同一个工作日入职。例如,一个员工的入职日期是 1988 年 3 月 10 日,星期一;另一个则是 2001 年 3 月 2 日,星期一。那么,由于二者的月份名称和星期值一致,你认为他们两个的入职日期是相匹配的。对于 EMP
表而言,只有 3 个员工符合这种条件。你希望得到的结果集如下所示。
SQL 比较特定的日期要素 解决方案
我们希望把一个员工的 HIREDATE
与另一个员工的 HIREDATE
相比较,因而需要对 EMP
表做自连接查询。这样每一种可能的 HIREDATE
组合都会被拿出来比较一下。然后,只需提取出每一个 HIREDATE
的星期值和月份并做比较即可。
DB2
EMP
表自连接之后,使用 DAYOFWEEK
函数返回一个数值表示星期几。使用 MONTHNAME
函数返回月份名称。
Oracle 和 PostgreSQL
EMP
自连接之后,使用 TO_CHAR
函数格式化 HIREDATE
得到筛选条件里的星期值和月份。
MySQL
EMP
表自连接之后,使用 DATE_FORMAT
函数格式化 HIREDATE
得到筛选条件里的星期值和月份。
SQL Server
EMP
自连接之后,使用 DATENAME
函数格式化 HIREDATE
得到筛选条件里的星期值和月份。
SQL 比较特定的日期要素 扩展知识
以上几种解决方案只在格式化 HIREDATE
时用到了不同的日期函数。下面的讨论部分将以 Oracle 和 PostgreSQL 的解决方案为例(因为该解决方案最为简短);尽管如此,下面的讲解内容也同样适用于其他解决方案。
首先用 EMP
表做自连接查询,这样每个员工都能访问其他员工的 HIREDATE
。我们来看一下下面的查询结果(只筛选出了与员工 SCOTT 相关的数据)。
通过 EMP
表自连接查询,我们把 SCOTT 的 HIREDATE
和所有其他员工的 HIREDATE
做了比较。筛选条件里的 EMPNO
表明 SCOTT 的 HIREDATE
不会作为 OTHER_HDS
列返回。下一步要使用数据库内置的日期格式化函数比较 HIREDATE
对应的星期值和月份,并只保留相匹配的行。
现在,HIREDATE
都已经正确地匹配出来了,但是我们得到了 6 行查询结果,而不是前面讲过的 3 行。这是因为筛选条件 EMPNO
导致了多余的行。使用“不等于”作为筛选条件,我们就没有办法过滤掉反向的查询结果。例如,上述第一行是 FORD 匹配 SCOTT 的结果,而最后一行则是 SCOTT 匹配 FORD。结果集里出现了 6 行数据,从技术上讲虽然没错,实际上却出现了重复数据。我们可以改用“小于”作为筛选条件以避免出现重复数据。(下面的查询语句去掉了 HIREDATE
,这样查询结果会更接近最终结果集。)
最后,只要把上述查询结果连接起来变成符合要求的内容即可。