我有可以标记时间范围状态的项目。在每一行中,我都有一个带标志的项目的开始和停止时间。
例如:
start stop itemid flag
1-Jan 1-Feb 1 a
1-Feb 1-Mar 1 b
1-Feb 1-Mar 2 a
1-Jan 1-Mar 3 a
1-Jan null 4 a
我需要的是一个计数的子计数。也就是说,对于给定的两个日期(例如1-Jan
和1-Mar
),我需要计算在第一个日期标记a
但不标记a
的项目数在第二次约会。 (还有其他一些因素,其中包括a
而非 - a
的其他3种组合。)
我还需要在任何一个日期(但不是两个)以某种方式解释没有标志,但是现在我可以假设没有标志是b
。
基本上,我需要计算以下情况:(a,a),(a,b),(a,null),(b,a),(b,b),(b,null); for(x,y),其中x是第一个日期的每个项目的标志,y是第二个日期的标志。
现有的,我可以计算一个日期存在多少个标记a
或b
。
select count(1)
from table
where start <= '2014-02-15'
and (stop >= '2014-02-15' or stop is null)
and flag = a
答案 0 :(得分:1)
这应该可以帮到你。
请注意,我将“stop&gt; ='2014-02-15'”更改为“stop&gt;'2014-02-15'”。
您需要确定“停止”日期是否在该间隔内。我假设不是因为你在项目1的开始和停止都有“1月2日”。否则项目1在1月2日的状态a和b都有。
select sum(case when d1.flag='a' and d2.flag='a' then 1 else 0 end) AA
,sum(case when d1.flag='a' and d2.flag='b' then 1 else 0 end) AB
,sum(case when d1.flag='a' and d2.flag is null then 1 else 0 end) Anull
,sum(case when d1.flag='b' and d2.flag='a' then 1 else 0 end) BA
,sum(case when d1.flag='b' and d2.flag='b' then 1 else 0 end) BB
,sum(case when d1.flag='b' and d2.flag is null then 1 else 0 end) Bnull
from
(
select *
from table
where start <= '2014-01-15'
and (stop > '2014-01-15' or stop is null)
and flag = 'a'
) d1
left join (
select *
from table
where start <= '2014-02-15'
and (stop > '2014-02-15' or stop is null)
and flag = 'a'
) d2 on d1.itemid = d2.itemid
答案 1 :(得分:1)
这可能会或可能不会比其他答案更好。虽然它不使用自联接,但它使用两次分组:子选择中的显式分组和PIVOT中的隐式分组。所以,在这一点上,我提供这个解决方案只是你尝试的另一个选择,因为另一个选项不适合你,according to your comment:
SELECT *
FROM (
SELECT
itemid,
S = ISNULL(MAX(CASE WHEN start <= @d1 AND (@d1 < stop OR stop IS NULL) THEN flag END), '_')
+ ISNULL(MAX(CASE WHEN start <= @d2 AND (@d2 < stop OR stop IS NULL) THEN flag END), '_')
FROM @table
WHERE start <= @d1 AND (@d1 < stop OR stop IS NULL)
OR start <= @d2 AND (@d2 < stop OR stop IS NULL)
GROUP BY
itemid
) AS s
PIVOT (COUNT(itemid) FOR S IN (aa, ab, a_, ba, bb, b_)) AS p
;
@d1
和@d2
是您参数化的日期。
子选择查找具有与至少一个日期参数匹配的数据的itemid
,然后确定每个itemid
在任一日期具有的状态,标记缺少具有下划线的状态。然后,它将两个状态组合成一个字符串值,作为列S
返回。因此,如果第一个日期的状态'a'
和另一个的状态相同,则生成的字符串将为'aa'
,如果是另一个示例,则第一个日期为'b'
,第二个日期没有数据,S
将为'b_'
,依此类推。
然后对结果集进行透视和聚合,S
列为透视结果提供列名称。请注意,派生表还可能返回字符串'_a'
和'_b'
。如果您决定将它们包含在PIVOT列列表中,那么它们也可能会得到非零结果。