我有一个表格,准确指定了每个员工在特定办公室的日期和时间。
EmployeeTable
看起来像这样:
我想为每个员工在办公室时准确选择最短和最长日期和时间:
我的 SQL 代码是:
with tab1 as
(
select *
from EmployeeTable
), tab2 as
(
select
t1.*,
case when lag(t1.EmployeeID) over(order by t1.id) is null then 1
when lag(t1.EmployeeID) over(order by t1.id) = t1.EmployeeID then 0
else 1
end lg
from tab1 t1
)
, tab3 as (
select t1.*,
sum(t1.lg) over(order by t1.id) grp
from tab2 t1
)
select t1.EmployeeID,
min(t1.DateP) as min,
TimeP,
max(t1.DateP)as max,
TimeP
from tab3 t1
group by t1.EmployeeID, t1.grp
但是上面的代码有错误。 每个人都可以帮助我吗?
最佳答案
这是一个间隙和岛屿问题。解决此问题的一种方法是使用行数差异法:
WITH cte AS (
SELECT *, ROW_NUMBER() OVER (ORDER BY DateP, TimeP) rn1,
ROW_NUMBER() OVER (PARTITION BY EmployeeID ORDER BY DateP, TimeP) rn2
FROM EmployeeTable
),
cte2 AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY EmployeeID, rn1 - rn2
ORDER BY DateP, TimeP) rn_first,
ROW_NUMBER() OVER (PARTITION BY EmployeeID, rn1 - rn2
ORDER BY DateP DESC, TimeP DESC) rn_last
FROM cte
)
SELECT
EmployeeID,
MAX(CASE WHEN rn_first = 1 THEN DateP END) AS MinDateP,
MAX(CASE WHEN rn_first = 1 THEN TimeP END) AS TimeMinDateP,
MAX(CASE WHEN rn_last = 1 THEN DateP END) AS MaxDateP,
MAX(CASE WHEN rn_last = 1 THEN TimeP END ) AS TimeMaxDateP
FROM cte2
GROUP BY
EmployeeID,
rn1 - rn2
ORDER BY
MIN(DateP),
MIN(TimeP);
请注意,如果您使用单个日期时间列来表示日期和时间,则第二个 CTE 中的逻辑将完全没有必要。像您当前所做的那样将日期和时间分开通常没有好处。
关于sql - 查找表中的最小和最大数据列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68608110/