合并各自的开始和结束日期,根据 Start/End 日期设置标志 - SQL
Merging Respective Start and End Dates, Setting Flag Depending on Start/End Date - SQL
问题:
我有一个 table 的交易(见下文),其中有 (open/start) 或 (close/end) 日期格式的交易。任务是将这些交易与其相应的日期合并,但是,也可能存在交易为 opened/started 而不是 closed/ended 的情况,在这种情况下,只需要显示开始日期,并且标记'Y' 已分配。在有结束日期的其他情况下,标志将为 'N'。我已经能够根据 first_value(Flag IGNORE NULLS) over(partition by Customer_ID order by EndDate desc) 的值设置一个标志,但是我在匹配开始时遇到了一些困难结束日期。
逻辑:
- 一天可以有多个开始和结束日期,只有时差。
- 每位客户每天只能进行一次开始和结束日期交易。
- 每个客户每天只能有开始日期(开放)交易。
- 标记 'N' 仅用于关闭的交易,'Y' 用于未完成的交易,即没有结束日期。
当前设置示例如下所示:
注意:对于这个特定的客户,我们有相同数量的交易(插入和删除,所以我知道标志将是 'N',当我们映射开始和结束日期时,但解决方案也必须在开始日期多于其他客户的结束日期,其中最终(最新)开始日期行的标志为 'Y'.
Customer_Id
Start Date
End Date
Flag
111
02/07/2020 20:58:32.000000
N
111
02/07/2020 19:18:04.000000
N
111
01/06/2020 09:38:49.000000
N
111
01/06/2020 09:36:34.000000
N
111
29/05/2020 16:58:07.000000
N
111
02/07/2020 20:57:52.000000
N
111
02/07/2020 19:17:22.000000
N
111
29/05/2020 16:58:06.000000
N
111
01/06/2020 09:38:40.000000
N
111
01/06/2020 09:36:34.000000
N
预期结果:
Customer_Id
Start Date
End Date
Flag
111
02/07/2020 20:57:52.000000
02/07/2020 20:58:32.000000
N
111
02/07/2020 19:17:22.000000
02/07/2020 19:18:04.000000
N
111
01/06/2020 09:38:40.000000
01/06/2020 09:38:49.000000
N
111
01/06/2020 09:36:34.00000
01/06/2020 09:36:34.000000
N
111
29/05/2020 16:58:06.000000
29/05/2020 16:58:07.000000
N
适用于上述示例的部分解决方案:
select customer_id
,start_date
,lead(end_date) -- find the next row's end date
over (partition by customer_id
order by coalesce(start_date, end_date)) as new_end
,case when new_end is null then 'Y' else 'N' end as flag
from tab
qualify start_date is not null -- only return starting rows
order by 1,2;
但是,如果开始日期多于结束日期(例如,几个关闭的交易,一个打开(不仅可以是 latest/newest 一个,也可以是中间的某个地方..))不行。例如。如果交易开放:开始日期 12/01/2019 09:36:34.00000 但没有结束日期
然后 lead() 跳过这个空结束日期值并分配下一个可用的结束日期,使解决方案看起来像这样:
Customer_Id
Start Date
End Date
Flag
111
02/07/2020 20:57:52.000000
02/07/2020 20:58:32.000000
N
111
02/07/2020 19:17:22.000000
02/07/2020 19:18:04.000000
N
111
01/06/2020 09:38:40.000000
01/06/2020 09:38:49.000000
N
111
12/01/2019 09:36:34.00000
18/11/2019 16:58:07.000000
N
111
18/11/2019 16:58:06.000000
NULL
NULL
什么时候应该是这样的:
Customer_Id
Start Date
End Date
Flag
111
02/07/2020 20:57:52.000000
02/07/2020 20:58:32.000000
N
111
02/07/2020 19:17:22.000000
02/07/2020 19:18:04.000000
N
111
01/06/2020 09:38:40.000000
01/06/2020 09:38:49.000000
N
111
12/01/2019 09:36:34.00000
NULL
Y
111
18/11/2019 16:58:06.000000
18/11/2019 16:58:07.000000
N
如何找到适合这两种情况的解决方案?
这将 return 每个开始日期的匹配结束日期。
select customer_id
,start_date
,lead(end_date) -- find the next row's end date
over (partition by customer_id
order by coalesce(start_date, end_date)) as new_end
,case when new_end is null then 'Y' else 'N' end as flag
from tab
qualify start_date is not null -- only return starting rows
order by 1,2;
问题: 我有一个 table 的交易(见下文),其中有 (open/start) 或 (close/end) 日期格式的交易。任务是将这些交易与其相应的日期合并,但是,也可能存在交易为 opened/started 而不是 closed/ended 的情况,在这种情况下,只需要显示开始日期,并且标记'Y' 已分配。在有结束日期的其他情况下,标志将为 'N'。我已经能够根据 first_value(Flag IGNORE NULLS) over(partition by Customer_ID order by EndDate desc) 的值设置一个标志,但是我在匹配开始时遇到了一些困难结束日期。
逻辑:
- 一天可以有多个开始和结束日期,只有时差。
- 每位客户每天只能进行一次开始和结束日期交易。
- 每个客户每天只能有开始日期(开放)交易。
- 标记 'N' 仅用于关闭的交易,'Y' 用于未完成的交易,即没有结束日期。
当前设置示例如下所示: 注意:对于这个特定的客户,我们有相同数量的交易(插入和删除,所以我知道标志将是 'N',当我们映射开始和结束日期时,但解决方案也必须在开始日期多于其他客户的结束日期,其中最终(最新)开始日期行的标志为 'Y'.
Customer_Id | Start Date | End Date | Flag |
---|---|---|---|
111 | 02/07/2020 20:58:32.000000 | N | |
111 | 02/07/2020 19:18:04.000000 | N | |
111 | 01/06/2020 09:38:49.000000 | N | |
111 | 01/06/2020 09:36:34.000000 | N | |
111 | 29/05/2020 16:58:07.000000 | N | |
111 | 02/07/2020 20:57:52.000000 | N | |
111 | 02/07/2020 19:17:22.000000 | N | |
111 | 29/05/2020 16:58:06.000000 | N | |
111 | 01/06/2020 09:38:40.000000 | N | |
111 | 01/06/2020 09:36:34.000000 | N |
预期结果:
Customer_Id | Start Date | End Date | Flag |
---|---|---|---|
111 | 02/07/2020 20:57:52.000000 | 02/07/2020 20:58:32.000000 | N |
111 | 02/07/2020 19:17:22.000000 | 02/07/2020 19:18:04.000000 | N |
111 | 01/06/2020 09:38:40.000000 | 01/06/2020 09:38:49.000000 | N |
111 | 01/06/2020 09:36:34.00000 | 01/06/2020 09:36:34.000000 | N |
111 | 29/05/2020 16:58:06.000000 | 29/05/2020 16:58:07.000000 | N |
适用于上述示例的部分解决方案:
select customer_id
,start_date
,lead(end_date) -- find the next row's end date
over (partition by customer_id
order by coalesce(start_date, end_date)) as new_end
,case when new_end is null then 'Y' else 'N' end as flag
from tab
qualify start_date is not null -- only return starting rows
order by 1,2;
但是,如果开始日期多于结束日期(例如,几个关闭的交易,一个打开(不仅可以是 latest/newest 一个,也可以是中间的某个地方..))不行。例如。如果交易开放:开始日期 12/01/2019 09:36:34.00000 但没有结束日期 然后 lead() 跳过这个空结束日期值并分配下一个可用的结束日期,使解决方案看起来像这样:
Customer_Id | Start Date | End Date | Flag |
---|---|---|---|
111 | 02/07/2020 20:57:52.000000 | 02/07/2020 20:58:32.000000 | N |
111 | 02/07/2020 19:17:22.000000 | 02/07/2020 19:18:04.000000 | N |
111 | 01/06/2020 09:38:40.000000 | 01/06/2020 09:38:49.000000 | N |
111 | 12/01/2019 09:36:34.00000 | 18/11/2019 16:58:07.000000 | N |
111 | 18/11/2019 16:58:06.000000 | NULL | NULL |
什么时候应该是这样的:
Customer_Id | Start Date | End Date | Flag |
---|---|---|---|
111 | 02/07/2020 20:57:52.000000 | 02/07/2020 20:58:32.000000 | N |
111 | 02/07/2020 19:17:22.000000 | 02/07/2020 19:18:04.000000 | N |
111 | 01/06/2020 09:38:40.000000 | 01/06/2020 09:38:49.000000 | N |
111 | 12/01/2019 09:36:34.00000 | NULL | Y |
111 | 18/11/2019 16:58:06.000000 | 18/11/2019 16:58:07.000000 | N |
如何找到适合这两种情况的解决方案?
这将 return 每个开始日期的匹配结束日期。
select customer_id
,start_date
,lead(end_date) -- find the next row's end date
over (partition by customer_id
order by coalesce(start_date, end_date)) as new_end
,case when new_end is null then 'Y' else 'N' end as flag
from tab
qualify start_date is not null -- only return starting rows
order by 1,2;