如何找到 运行 总日期和列的指定值?
How to find the running total over dates and specified value of a column?
下面是我的数据集的样子:
[1]: https://i.stack.imgur.com/v6r9J.png
CustNumber Status Date Running Total of Days
C100 IN 10/10/2019
C100 OUT 10/11/2019 1
C100 IN 10/12/2019
C100 OUT 10/13/2019 1
C100 IN 10/16/2019
C100 OUT 10/17/2019 1
C100 IN 4/23/2020
C100 OUT 4/27/2020
C100 OUT 4/28/2020
C100 OUT 4/28/2020 5
C100 IN 10/13/2020
C100 OUT 10/19/2020 6
我想在每次“状态”列的值从 IN 变为 OUT 时计算 运行 总天数列。在 2019 年 10 月 10 日,该值为 IN。在 2019 年 10 月 11 日,该值为 OUT。所以 运行 总数应该是 1.
对于同一位客户,在 2019 年 4 月 23 日,该值为 IN。在 04 月 28 日,该值再次为 OUT。所以 运行 总数应该是 5,因为它处于 'IN' 状态 5 天。
如何在 SQL 中实现此查询?
我会把它作为一个缺口和孤岛问题来解决。每当看到“IN”状态时,一个岛就开始了:我们可以使用“IN”状态的 window 计数来识别这些“相邻”记录组,然后是日期算法:
select t.*,
date - min(date) over(partition by grp) as running_total_of_days
from (
select t.*,
sum(case when status = 'IN' then 1 else 0 end)
over(partition by custnumber order by date) as grp
from mytable t
) t
计算日期差异的实际语法确实因数据库而异 - 而且您没有告诉您使用的是哪个。以上适用于支持直接减去日期的数据库(例如 Oracle 或 Postgres);其他数据库具有等效的语法或功能。
这会使每一行的总计 运行。如果您只想在每个组的最后一个“OUT”行上使用它,您可以使用 case
表达式:
select t.*,
case when status = 'OUT' and row_number() over(partition by grp order by date desc) = 1
then date - min(date) over(partition by grp)
end as running_total_of_days
from (
select t.*,
sum(case when status = 'IN' then 1 else 0 end)
over(partition by custnumber order by date) as grp
from mytable t
) t
下面是我的数据集的样子: [1]: https://i.stack.imgur.com/v6r9J.png
CustNumber Status Date Running Total of Days
C100 IN 10/10/2019
C100 OUT 10/11/2019 1
C100 IN 10/12/2019
C100 OUT 10/13/2019 1
C100 IN 10/16/2019
C100 OUT 10/17/2019 1
C100 IN 4/23/2020
C100 OUT 4/27/2020
C100 OUT 4/28/2020
C100 OUT 4/28/2020 5
C100 IN 10/13/2020
C100 OUT 10/19/2020 6
我想在每次“状态”列的值从 IN 变为 OUT 时计算 运行 总天数列。在 2019 年 10 月 10 日,该值为 IN。在 2019 年 10 月 11 日,该值为 OUT。所以 运行 总数应该是 1.
对于同一位客户,在 2019 年 4 月 23 日,该值为 IN。在 04 月 28 日,该值再次为 OUT。所以 运行 总数应该是 5,因为它处于 'IN' 状态 5 天。
如何在 SQL 中实现此查询?
我会把它作为一个缺口和孤岛问题来解决。每当看到“IN”状态时,一个岛就开始了:我们可以使用“IN”状态的 window 计数来识别这些“相邻”记录组,然后是日期算法:
select t.*,
date - min(date) over(partition by grp) as running_total_of_days
from (
select t.*,
sum(case when status = 'IN' then 1 else 0 end)
over(partition by custnumber order by date) as grp
from mytable t
) t
计算日期差异的实际语法确实因数据库而异 - 而且您没有告诉您使用的是哪个。以上适用于支持直接减去日期的数据库(例如 Oracle 或 Postgres);其他数据库具有等效的语法或功能。
这会使每一行的总计 运行。如果您只想在每个组的最后一个“OUT”行上使用它,您可以使用 case
表达式:
select t.*,
case when status = 'OUT' and row_number() over(partition by grp order by date desc) = 1
then date - min(date) over(partition by grp)
end as running_total_of_days
from (
select t.*,
sum(case when status = 'IN' then 1 else 0 end)
over(partition by custnumber order by date) as grp
from mytable t
) t