Sql server 使用布尔条件计算具有条件sql的月份

Sql server 使用布尔条件计算具有条件sql的月份,sql-server,sql-server-2012,gaps-and-islands,Sql Server,Sql Server 2012,Gaps And Islands,我有一张这样的桌子: ---id---datetime---month---active 1 2016-12-01 Dec-16 0 1 2016-12-02 Dec-16 1 1 2017-01-28 Jan-17 1 1 2017-02-03 Feb-17 0 1 2017-02-24 Feb-17 0 1 2017-03-05 Mar-17 0 1 2017-03-24 Mar-1

我有一张这样的桌子:

---id---datetime---month---active
    1   2016-12-01  Dec-16  0
    1   2016-12-02  Dec-16  1
    1   2017-01-28  Jan-17  1
    1   2017-02-03  Feb-17  0
    1   2017-02-24  Feb-17  0
    1   2017-03-05  Mar-17  0
    1   2017-03-24  Mar-17  1
    1   2017-04-02  Apr-17  1
    1   2017-04-25  Apr-17  1
    1   2017-05-02  May-17  1
    1   2017-05-28  May-17  0
我希望得到这样的结果:

---id---monthCount---Active
    1       1          0
    1       2          1
    1       2          0
    1       3          1
    1       1          0
该表的id不超过1个
id

现在,我只是通过使用分区和排序(按
id
active
和排序(按
datetime
)来获得最小日期和最大日期之间的差异,但这给了我从第一次变为1到最后变为0的月份。我希望通过每次更改
active
将其详细分开


我怎样才能做到这一点

您可以使用行号的差异来识别组(这是一个间隙和孤岛问题)。最后的解决方案需要
计数(不同)


这是假设数据是按id、month、active排序的——这是问题中数据的排序。最好使用一个列来明确定义行的排序顺序。

在sql server 2012+中,您可以像这样使用
LAG

DECLARE @SampleData AS TABLE
(
    id int,
    [datetime] datetime,
    active bit
)


;WITH temp AS
(
    SELECT   sd.id,
          sd.active, 
          sd.[datetime],
          lag(sd.active) over(PARTITION BY sd.id ORDER BY sd.datetime) AS previousActive,
          lag(sd.id) over( ORDER BY sd.id, sd.datetime) AS previousId
    FROM @SampleData sd
)
,temp1 AS
(
    SELECT *, 
          sum(CASE WHEN t.previousActive IS NULL OR t.previousActive != t.active OR t.id != t.previousId THEN 1 
             ELSE 0 END) 
          OVER(PARTITION BY t.id ORDER BY t.[datetime]) AS groupid
    FROM temp t
)
SELECT t.id, count(DISTINCT month(t.datetime)) AS monthCount, t.active  
FROM temp1 t
GROUP BY id, t.groupid, t.active

演示链接:

括号是什么?当我试图运行代码时,由于语法不正确,我遇到了一个错误,而且我从未见过这样的分组。你能解释一下吗?这是个错误吗?
DECLARE @SampleData AS TABLE
(
    id int,
    [datetime] datetime,
    active bit
)


;WITH temp AS
(
    SELECT   sd.id,
          sd.active, 
          sd.[datetime],
          lag(sd.active) over(PARTITION BY sd.id ORDER BY sd.datetime) AS previousActive,
          lag(sd.id) over( ORDER BY sd.id, sd.datetime) AS previousId
    FROM @SampleData sd
)
,temp1 AS
(
    SELECT *, 
          sum(CASE WHEN t.previousActive IS NULL OR t.previousActive != t.active OR t.id != t.previousId THEN 1 
             ELSE 0 END) 
          OVER(PARTITION BY t.id ORDER BY t.[datetime]) AS groupid
    FROM temp t
)
SELECT t.id, count(DISTINCT month(t.datetime)) AS monthCount, t.active  
FROM temp1 t
GROUP BY id, t.groupid, t.active