我正在嘗試根據下表中的資料找出如何回傳開始日期和結束日期:
| 姓名 | 日期從 | 日期至 |
|---|---|---|
| 一種 | 2022-01-03 | 2022-01-03 |
| 一種 | 2021-12-29 | 2021-12-31 |
| 一種 | 2021-12-28 | 2021-12-28 |
| 一種 | 2021-12-27 | 2021-12-27 |
| 一種 | 2021-12-23 | 2021-12-24 |
| 一種 | 2021-11-08 | 2021-11-09 |
我所追求的結果將如下所示:
| 姓名 | 日期從 | 日期至 |
|---|---|---|
| 一種 | 2021-12-23 | 2022-01-03 |
| 一種 | 2021-11-08 | 2021-11-09 |
第一個表中的日期有時會與 Date From 和 Date To 一起超過周末,但如果該行在周五結束而下一行從下周一開始,則需要將其歸類為相同的“塊”,如圖所示在第二個表中。我希望使用DATEFIRST設定來滿足周末的需求,以避免使用日歷表,如如何在 SQL Server 查詢中排除周末天數?,但如果日歷表最終成為最簡單的方法,我很樂意考慮創建一個。
在上面的示例中,我只有 1 個名稱,但該表將有多個名稱,并且需要按名稱進行分組。
我看到的唯一例子是只使用 1 個日期列作為記錄,我努力改變他們的代碼來滿足我的例子。我找到的最接近的示例對我不起作用,因為它基于日期時間欄位和時差 -在多行中查找連續日期的開始和停止日期
uj5u.com熱心網友回復:
這是一個間隙和島嶼問題,您需要考慮周末的連續性。
你可以做:
select max(name) as name, min(date_from) as date_from, max(date_to) as date_to
from (
select *, sum(inc) over(order by date_to) as grp
from (
select *,
case when lag(ext_to) over(order by date_to) = date_from
then 0 else 1 end as inc
from (
select *,
case when (datepart(weekday, date_to) = 6)
then dateadd(day, 3, date_to)
else dateadd(day, 1, date_to) end as ext_to
from t
) x
) y
) z
group by grp
結果:
name date_from date_to
---- ---------- ----------
A 2021-11-08 2021-11-09
A 2021-12-23 2022-01-03
請參閱db<>fiddle #1處的運行示例。
注意:您的問題沒有提到它,但您可能想要按人細分。我沒有做。
編輯:按名稱添加磁區
按名稱磁區實際上很容易。以下查詢執行此操作:
select name, min(date_from) as date_from, max(date_to) as date_to
from (
select *, sum(inc) over(partition by name order by date_to) as grp
from (
select *,
case when lag(ext_to) over(partition by name order by date_to) = date_from
then 0 else 1 end as inc
from (
select *,
case when (datepart(weekday, date_to) = 6)
then dateadd(day, 3, date_to)
else dateadd(day, 1, date_to) end as ext_to
from t
) x
) y
) z
group by name, grp
order by name, grp
請參閱在db<>fiddle #2處運行查詢。
uj5u.com熱心網友回復:
with extended as (
select dtto, case when datepart(weekday, dtfrom) = 5 then dateadd (day, 2, dtfrom) else from end as dtfrom
from data
), adjacent as (
select *,
case when dateadd(day, 1
lag(dtfrom) over (partition by name order by dtto)) = dtto then 0 else 1 end as brk
from extended
), blocked as (
select *, sum(brk) over (partition by name order by dtto) as grp
from adjacent
)
select name, min(dtto), max(dtfrom) from grouped
group by name, grp
這將是接近的。您的需求中的一些細節將很容易合并。我假設范圍不重疊。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/346159.html
標籤:sql sql-server 短信
