在给定日期前一天计算的self join

7tofc5zh  于 2021-07-29  发布在  Java
关注(0)|答案(3)|浏览(291)

我有一个表employee\u hire,它有一个部门的雇员(id)的雇用日期。现在我想写一个select查询,它再添加一列(last_day)来显示他在那个部门工作的最后一天。例如,对于d01部门的id=1,他的最后一天是2014/12/31。同样,在d02,他的最后一天是2017/12/31。
现在,由于他仍在d04工作,我们可以有一个字符串,如'直到现在'或一个未来的日期,如2099/12/31或任何服务的目的。
我想为表中的每个员工都这样做。

+---+-------------+------------+
| 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 |
+---+-------------+------------+

我知道这可以通过使用超前或滞后函数来实现,但是有人能告诉我如何使用自连接来实现吗?
提前谢谢!!

ki1q1bka

ki1q1bka1#

假设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\ u number()函数的情况下,如何在按任意条件排序时进行自联接。

c86crjj0

c86crjj02#

你可以用 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 ),第三个是默认值,即为分区中的“最后”行返回的值。
如果要在没有窗口函数的情况下执行此操作,我建议编译横向联接或子查询:

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
)
rfbsl7qr

rfbsl7qr3#

我想通常我会选择一个window函数,但是如果这个函数不在表中,并且您的数据没有太多的列,那么结合分组的self join看起来会非常干净:

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

相关问题