Self Join 计算给定日期前一天
Self Join to calcuate one day before a given date
我有这个 table Employee_Hire,其中有部门员工 (ID) 的雇用日期。现在,我想编写一个 Select 查询,其中再添加一列 (Last_day) 以显示他在该部门工作的最后一天。例如,对于部门 D01 中的 ID = 1,他的最后一天是 2014/12/31。同样在 D02 中,他的最后一天是 2017/12/31。
现在,由于他仍在 D04 工作,我们可以使用 'Till Present' 之类的字符串或 2099/12/31 之类的未来日期或任何符合此目的的日期。
我想为 table 中的每位员工执行此操作。
+---+-------------+------------+
| Id| Dept_name | Hiredate |
+---+-------------+------------+
| 1 | D01 | 2012-01-01 |
| 1 | D02 | 2015-01-01 |
| 1 | D03 | 2018-01-01 |
| 1 | D04 | 2019-01-01 |
| 2 | D01 | 2010-01-01 |
| 2 | D02 | 2012-01-01 |
| 3 | D01 | 2008-01-01 |
| 3 | D02 | 2010-01-01 |
| 3 | D03 | 2012-01-01 |
| 4 | D01 | 2015-01-01 |
| 4 | D02 | 2017-01-01 |
+---+-------------+------------+
我知道这可以使用 LEAD OR LAG 函数来完成,但是谁能告诉我如何使用 Self Join 来完成吗?
提前致谢!!
您可以使用 lead()
和日期算法:
select
t.*,
dateadd(
day,
-1,
lead(hiredate, 1, '2100-01-01') over(partition by id order by hiredate)
) last_day
from mytable t
lead()
的第二个参数是偏移量(这里,你想要 "next" 行,所以 1
),第三个是默认值,返回给分区中的 "last" 行。
如果您想在没有 window 函数的情况下执行此操作,我建议使用横向连接或子查询:
select t.*, x.last_day
from mytable t
cross apply (
select dateadd(
day,
-1,
coalesce(min(t1.hiredate), 2100-01-01')
) last_day
from mytable t1
where t1.id = t.id and t1.hiredate > t.hiredate
)
假设 ROW_NUMBER() 函数也没有限制,此查询使用实际的自连接:
SELECT
curr.Id,
curr.Dept_name,
curr.Hiredate,
DATEADD(day, -1, next.Hiredate) AS Last_day
FROM
(
SELECT *, ROW_NUMBER() OVER (PARTITION BY ID ORDER BY HireDate) AS RowNum
FROM EmployeeHire
) AS curr
LEFT OUTER JOIN
(
SELECT *, ROW_NUMBER() OVER (PARTITION BY ID ORDER BY HireDate) AS RowNum
FROM EmployeeHire
) AS next
ON curr.ID = next.ID AND curr.RowNum = next.RowNum - 1
我不确定在没有 ROW_NUMBER() 函数的情况下按任意条件排序时如何进行自连接。
我认为通常我会使用 window 函数,但如果 table 不适用并且您的数据没有太多列,则自连接与分组相结合可以看起来很干净:
select a.id, a.Dept_name, a.Hiredate,
last_day = dateadd(day, -1, min(b.Hiredate))
from @hireData a
left join @hireData b on a.Id = b.Id and b.Hiredate > a.Hiredate
group by a.id, a.Dept_name, a.Hiredate
我有这个 table Employee_Hire,其中有部门员工 (ID) 的雇用日期。现在,我想编写一个 Select 查询,其中再添加一列 (Last_day) 以显示他在该部门工作的最后一天。例如,对于部门 D01 中的 ID = 1,他的最后一天是 2014/12/31。同样在 D02 中,他的最后一天是 2017/12/31。
现在,由于他仍在 D04 工作,我们可以使用 'Till Present' 之类的字符串或 2099/12/31 之类的未来日期或任何符合此目的的日期。
我想为 table 中的每位员工执行此操作。
+---+-------------+------------+
| Id| Dept_name | Hiredate |
+---+-------------+------------+
| 1 | D01 | 2012-01-01 |
| 1 | D02 | 2015-01-01 |
| 1 | D03 | 2018-01-01 |
| 1 | D04 | 2019-01-01 |
| 2 | D01 | 2010-01-01 |
| 2 | D02 | 2012-01-01 |
| 3 | D01 | 2008-01-01 |
| 3 | D02 | 2010-01-01 |
| 3 | D03 | 2012-01-01 |
| 4 | D01 | 2015-01-01 |
| 4 | D02 | 2017-01-01 |
+---+-------------+------------+
我知道这可以使用 LEAD OR LAG 函数来完成,但是谁能告诉我如何使用 Self Join 来完成吗?
提前致谢!!
您可以使用 lead()
和日期算法:
select
t.*,
dateadd(
day,
-1,
lead(hiredate, 1, '2100-01-01') over(partition by id order by hiredate)
) last_day
from mytable t
lead()
的第二个参数是偏移量(这里,你想要 "next" 行,所以 1
),第三个是默认值,返回给分区中的 "last" 行。
如果您想在没有 window 函数的情况下执行此操作,我建议使用横向连接或子查询:
select t.*, x.last_day
from mytable t
cross apply (
select dateadd(
day,
-1,
coalesce(min(t1.hiredate), 2100-01-01')
) last_day
from mytable t1
where t1.id = t.id and t1.hiredate > t.hiredate
)
假设 ROW_NUMBER() 函数也没有限制,此查询使用实际的自连接:
SELECT
curr.Id,
curr.Dept_name,
curr.Hiredate,
DATEADD(day, -1, next.Hiredate) AS Last_day
FROM
(
SELECT *, ROW_NUMBER() OVER (PARTITION BY ID ORDER BY HireDate) AS RowNum
FROM EmployeeHire
) AS curr
LEFT OUTER JOIN
(
SELECT *, ROW_NUMBER() OVER (PARTITION BY ID ORDER BY HireDate) AS RowNum
FROM EmployeeHire
) AS next
ON curr.ID = next.ID AND curr.RowNum = next.RowNum - 1
我不确定在没有 ROW_NUMBER() 函数的情况下按任意条件排序时如何进行自连接。
我认为通常我会使用 window 函数,但如果 table 不适用并且您的数据没有太多列,则自连接与分组相结合可以看起来很干净:
select a.id, a.Dept_name, a.Hiredate,
last_day = dateadd(day, -1, min(b.Hiredate))
from @hireData a
left join @hireData b on a.Id = b.Id and b.Hiredate > a.Hiredate
group by a.id, a.Dept_name, a.Hiredate