我需要在同一LegalStart / LegalEnd日期内找到第一个StayStart,其中> = 8天(LOS)且仅为Type 1。类型1的连续停留少于8天,如果它们加起来最多8天并且没有其他类型中断它们。在那种情况下,我需要最早的连续住宿。这就是我无法弄清楚如何处理的问题。添加8个以下但连续8个的连续住宿。我很想发布我尝试过的东西,但是我已经无处可去了。
这是我的表:
cust# LegalStart StayStart StayEnd LegalEnd Type LOS(days)
1000 5/3/2013 2/1/2016 2/5/2016 11/18/2016 1 4
1000 5/3/2013 2/5/2016 2/8/2016 11/18/2016 1 3
1000 5/3/2013 2/8/2016 2/11/2016 11/18/2016 2 3
1000 5/3/2013 2/11/2016 2/28/2016 11/18/2016 1 17
1000 3/2/2016 3/2/2016 3/5/2016 11/18/2016 1 4
1000 3/2/2016 3/5/2016 3/7/2016 11/18/2016 1 2
1000 3/2/2016 3/7/2016 3/11/2016 11/18/2016 1 4
1000 3/2/2016 3/12/2016 3/22/2016 11/18/2016 1 10
2000 3/1/2011 12/1/2015 12/3/2015 1/8/2016 1 2
2000 3/1/2011 12/3/2015 12/5/2015 1/8/2016 1 2
2000 3/1/2011 12/5/2015 12/6/2015 1/8/2016 1 1
2000 3/1/2011 12/6/2015 12/18/2015 1/8/2016 1 12
预期结果
cust# LegalStart StayStart StayEnd LegalEnd Type LOS(days)
1000 5/3/2013 2/11/2016 2/28/2016 11/18/2016 1 17
1000 3/2/2016 3/2/2016 3/5/2016 11/18/2016 1 4
2000 3/1/2011 12/1/2015 12/3/2015 1/8/2016 1 2
我的第一个结果是具有17个LOS的结果,因为之前该客户的行确实累计最多10天,其中一个保留是类型2,因此它不计算在内。其他2次入住最多可累计7天,因此不计算在内。因此,2016年11月11日StaySart(LOS为17)是符合我标准的最短日期 同一个cust#的第二个结果是在下一个法定日期时间范围内,4天的停留加上接下来的2天和4天的2次停留都是类型1,因此他们加起来超过或者= 8天。因此,2016年3月2日的StayStart日期是符合我标准的最短日期 第三个结果行是下一个客户,这是正确的,因为该客户的所有4行都是类型1,并且加起来> = 8天。因此,2015年12月1日的StayStart是符合我标准的最短日期 感谢您提供的任何帮助。
答案 0 :(得分:0)
这在MySQL中有点乱,它缺乏对分析函数的支持,但可以使用变量来完成,如下所示(假设你的表名为“theTable”):
select custNum, legalStart, legalEnd, stayStart, stayEnd, type, losDays from (
select
@custNum as custNum,
@legalStart as legalStart,
@legalEnd as legalEnd,
@stayStart as stayStart,
@stayEnd as stayEnd,
@type as type,
@losDays as losDays,
@newGroup :=
(@custNum != custNum
or @legalStart != legalStart
or @legalEnd != legalEnd
or @type != type)
as newGroup,
@aggLosDays as groupAggLosDays,
@aggLosDays :=
case when @newGroup
then losDays
else @aggLosDays + losDays end as __________,
case when @newGroup then @losDays := losDays else null end as _,
@custNum :=
case when @custNum != custNum
then custNum else @custNum end as ___,
@legalStart :=
case when @legalStart != legalStart
then legalStart else @legalStart end as ____,
@legalEnd :=
case when @legalEnd != legalEnd
then legalEnd else @legalEnd end as _____,
@type :=
case when @type != type
then type else @type end as ______,
@stayStart :=
case when @newGroup
then stayStart else @stayStart end as _______,
@stayEnd :=
case when @newGroup
then stayEnd else @stayEnd end as ________
from
(
(
select
custNum, legalStart, legalEnd, stayStart, stayEnd,
type, datediff(stayEnd,stayStart) as losDays
from theTable
order by custNum, legalStart, legalEnd, stayStart, type
) union all (
select -1, date('0000-00-00'), date('0000-00-00'),
date('0000-00-00'), date('0000-00-00'), -1, null
)
) tt
join (select @aggLosDays := -1) z1
join (select @custNum := -1) z2
join (select @legalStart := date('0000-00-00')) z3
join (select @legalEnd := date('0000-00-00')) z4
join (select @stayStart := date('0000-00-00')) z5
join (select @staylEnd := date('0000-00-00')) z6
join (select @type := -1) z7
join (select @losDays := null) z8
order by
custNum,
legalStart,
legalEnd,
stayStart,
stayEnd,
type,
losDays
) z
where
newGroup
and type=1
and groupAggLosDays >= 8
;
此查询使用变量计算具有相同客户,法定日期范围和类型的组之间的运行总计。棘手的部分是从内部查询返回的每一行实际上不包含来自当前“theTable”行的任何数据,而是包含表示同一组中先前行的汇总日期的变量内容。当客户,合法日期范围或类型发生更改时,@ newGroup变量设置为TRUE,表示新组的开始。外部查询的where子句将从内部查询中选择一行(如果它被标记为新组),其类型为1且总天数> = 8。
“stub”行被追加到查询的“theTable”行,以触发最终组的处理。
MySQL不是我的主要RDBMS,所以我相信这可以变得更干净。
答案 1 :(得分:0)
这是一个适用于支持分析功能的MS SQL Server版本的版本。
select distinct custNum, legalStart, stayStart, stayEnd, legalEnd, type, losDays
from (
select
custNum, legalStart, legalEnd, type,
first_value(stayStart) over (partition by gg order by stayStart) as stayStart,
first_value(stayEnd) over (partition by gg order by stayEnd) as stayEnd,
first_value(losDays) over (partition by gg order by stayEnd) as losDays,
sum(losDays) over (partition by gg order by stayStart) as accLosDays
from (
select
custNum, legalStart, legalEnd, stayStart, stayEnd, type, losDays,
case when g is not null
then g
else min(g) over (
partition by custNum, legalStart, legalEnd
rows between current row and unbounded following)
end as gg
from (
select
custNum, legalStart, legalEnd, stayStart, stayEnd, type,
datediff(day,stayStart,stayEnd) as losDays,
case
when lead(type, 1, -1)
over (partition by custNum, legalStart, legalEnd order by stayStart) != type
then row_number() over ()
else null end as g
from
theTable
order by
custNum,
legalStart,
legalEnd,
stayStart,
type
) z
) zz
where
type=1
) zzz
where
accLosDays >= 8;
为了理解它是如何工作的,我建议运行每个select语句,从最里面开始并向外工作:
select
custNum, legalStart, legalEnd, stayStart, stayEnd, type,
datediff(day,stayStart,stayEnd) as losDays,
case
when lead(type, 1, -1)
over (partition by custNum, legalStart, legalEnd order by stayStart) != type
then row_number() over ()
else null end as g
from
theTable
order by
custNum,
legalStart,
legalEnd,
stayStart,
type
此查询按行和法定日期范围将表行分组到分区中。每个组的最后一行(由分区末尾或类型列值的更改确定)触发当前整体行号分配给名为g的输出列,否则g保留为null。 / p>
下一个查询“up”将使用g set的值获取这些行,并发出一个新列gg,该列填充g的空值以及其组的正确值:
select
custNum, legalStart, legalEnd, stayStart, stayEnd, type, losDays,
case
when g is not null
then g
else min(g) over (
partition by custNum, legalStart, legalEnd
rows between current row and unbounded following
) end as gg
from
<<<<inner query>>>>
最后,将第一个stayStart,stayEnd和losDays值拉出结果,按类型和每个组的总天数进行过滤:
select distinct
custNum, legalStart, stayStart, stayEnd, legalEnd, type, losDays
from (
select
custNum, legalStart, legalEnd, type,
first_value(stayStart)
over (partition by gg order by stayStart) as stayStart,
first_value(stayEnd)
over (partition by gg order by stayEnd) as stayEnd,
first_value(losDays)
over (partition by gg order by stayEnd) as losDays,
sum(losDays)
over (partition by gg order by stayStart) as accLosDays
from (
<<<<inner query>>>>
where
type=1
) zzz
where
accLosDays >= 8