SQL 服务器 - 按标志汇总日期
SQL Server - summarize dates by a flag
我正在使用 SQL Server 2008(尽管如果需要可以访问 SQL 2017)并且 table 是这样的:
DECLARE @tbl TABLE (recdate DATE, myflag BIT)
table 有一个范围内所有日期的行,myflag 位会时断时续,像这样:
recdate | myflag
2017-01-01 | 1
2017-01-02 | 1
2017-01-03 | 1
...
2017-04-03 | 1
2017-04-04 | 0
2017-04-05 | 0
..
2017-05-15 | 0
2017-05-16 | 1
etc.
但我真正需要做的是
period_from | period_to | myflag
2017-01-01 | 2017-04-03 | 1
2017-04-04 | 2017-05-15 | 0
2017-05-16 | 2017-05-21 | 1
因此每次 myflag 更改时,它都会创建一个新行并且前一行设置了结束日期(如果有意义的话)
我确定有一个非常明显的方法可以做到这一点,但我准备好 bash 我的头靠在墙上..我已经来回选择和子选择和插入和更新临时 tables,甚至尝试游标(我知道!但它是一次性查询)
这是一个缺口和孤岛问题。为此,您可以使用不同的行号:
select min(recdate) as period_from, max(recdate) as period_to, flag
from (select t.*,
row_number() over (order by recdate) as seqnum,
row_number() over (partition by flag order by recdate) as seqnum_f
from @tbl t
) t
group by (seqnum - seqnum_f), flag;
为什么这行得通用文字解释起来有点棘手。我发现如果你 运行 子查询,你会明白为什么你正在寻找的组的差异是恒定的。
如果您的日期是连续的,没有间隔、重复或时间成分,您可以做稍微简单的事情:
select min(recdate) as period_from, max(recdate) as period_to, flag
from (select t.*,
dateadd(day,
- row_number() over (partition by flag order by recdate
recdate
) as grp
from @tbl t
) t
group by grp, flag;
这和第一个版本的逻辑基本一样
我正在使用 SQL Server 2008(尽管如果需要可以访问 SQL 2017)并且 table 是这样的:
DECLARE @tbl TABLE (recdate DATE, myflag BIT)
table 有一个范围内所有日期的行,myflag 位会时断时续,像这样:
recdate | myflag
2017-01-01 | 1
2017-01-02 | 1
2017-01-03 | 1
...
2017-04-03 | 1
2017-04-04 | 0
2017-04-05 | 0
..
2017-05-15 | 0
2017-05-16 | 1
etc.
但我真正需要做的是
period_from | period_to | myflag
2017-01-01 | 2017-04-03 | 1
2017-04-04 | 2017-05-15 | 0
2017-05-16 | 2017-05-21 | 1
因此每次 myflag 更改时,它都会创建一个新行并且前一行设置了结束日期(如果有意义的话)
我确定有一个非常明显的方法可以做到这一点,但我准备好 bash 我的头靠在墙上..我已经来回选择和子选择和插入和更新临时 tables,甚至尝试游标(我知道!但它是一次性查询)
这是一个缺口和孤岛问题。为此,您可以使用不同的行号:
select min(recdate) as period_from, max(recdate) as period_to, flag
from (select t.*,
row_number() over (order by recdate) as seqnum,
row_number() over (partition by flag order by recdate) as seqnum_f
from @tbl t
) t
group by (seqnum - seqnum_f), flag;
为什么这行得通用文字解释起来有点棘手。我发现如果你 运行 子查询,你会明白为什么你正在寻找的组的差异是恒定的。
如果您的日期是连续的,没有间隔、重复或时间成分,您可以做稍微简单的事情:
select min(recdate) as period_from, max(recdate) as period_to, flag
from (select t.*,
dateadd(day,
- row_number() over (partition by flag order by recdate
recdate
) as grp
from @tbl t
) t
group by grp, flag;
这和第一个版本的逻辑基本一样