问题
I have an sql table that has something similar to this:
EmpNo StartTime EndTime
------------------------------------------
1 7:00 7:30
1 7:15 7:45
1 13:40 15:00
2 8:00 14:00
2 8:30 9:00
3 10:30 14:30
I've seen a lot of examples where you can find the gaps between everything, and a lot of examples where you can pack overlaps for everything. But I want to be able to separate these out by user.
Sadly, I need a pure SQL solution.
Ultimately, I would like to return:
EmpNo StartTime EndTime
------------------------------------------
1 7:00 7:45
1 13:40 15:00
2 8:00 14:00
3 10:30 14:30
It seems simple enough, I have just spent the last day trying to figure it out, and come up with very little. Never will any column here be NULL, and you can assume there could be duplicates, or gaps of 0.
I know this is the classic island problem, but the solutions I have seen so far aren't incredibly friendly with keeping separate ID's grouped
回答1:
"Pure SQL" would surely support the lag()
, lead()
, and cumulative sum functions because these are part of the standard. Here is a solution using standard SQL:
select EmpNo, min(StartTime) as StartTime, max(EndTime) as EndTime
from (select t.*, sum(StartGroup) over (partition by EmpNo order by StartTime) as grp
from (select t.*,
(case when StartTime <= lag(EndTime) over (partition by EmpNo order by StartTime)
then 0
else 1
end) as StartGroup
from table t
) t
) t
group by EmpNo, grp;
If your database doesn't support these, you can implement the same logic using correlated subqueries.
来源:https://stackoverflow.com/questions/24146989/sql-time-packing-of-islands