计算SQL Server中的运行计数,不包括某些行

时间:2014-09-04 12:08:24

标签: sql sql-server tsql sql-server-2012

这是我的表/源数据,

|---------------------------------------------------|
|ID     | DT            | DAY       | ATTENDANCE    |
|-------+---------------+-----------+---------------|
|89     | 2014-08-23    | NULL      | 1             |
|90     | 2014-08-24    | Sunday    | NULL          |
|91     | 2014-08-25    | NULL      | 1             |
|92     | 2014-08-26    | NULL      | 1             |
|93     | 2014-08-27    | NULL      | 0             |
|94     | 2014-08-28    | NULL      | 1             |
|95     | 2014-08-29    | NULL      | 0             |
|96     | 2014-08-30    | NULL      | 1             |
|97     | 2014-08-31    | Sunday    | NULL          |
|98     | 2014-08-01    | NULL      | 1             |
|99     | 2014-08-02    | NULL      | 1             |
|100    | 2014-08-03    | NULL      | 0             |
|101    | 2014-08-04    | NULL      | 0             |
|102    | 2014-08-05    | NULL      | 1             |
|103    | 2014-08-06    | NULL      | 1             |
|104    | 2014-08-07    | Sunday    | NULL          |
|105    | 2014-08-08    | NULL      | 1             |
|106    | 2014-08-09    | NULL      | 1             |
|107    | 2014-08-10    | NULL      | 1             |
|---------------------------------------------------|

我想要给出一个结果。第5列[Streak]是我想要计算的。它是根据出勤率计算的值。在任何一天,如果[ATTENDANCE] = 0[Streak]重置为0。

|-------------------------------------------------------------|
|ID     | DT            | DAY       | ATTENDANCE    | Streak  |
|-------+---------------+-----------+---------------+---------|
|89     | 2014-08-23    | NULL      | 1             | 1       |
|90     | 2014-08-24    | Sunday    | NULL          |         |
|91     | 2014-08-25    | NULL      | 1             | 2       |
|92     | 2014-08-26    | NULL      | 1             | 3       |
|93     | 2014-08-27    | NULL      | 0             | 0       |
|94     | 2014-08-28    | NULL      | 1             | 1       |
|95     | 2014-08-29    | NULL      | 0             | 0       |
|96     | 2014-08-30    | NULL      | 1             | 1       |
|97     | 2014-08-31    | Sunday    | NULL          |         |
|98     | 2014-08-01    | NULL      | 1             | 2       |
|99     | 2014-08-02    | NULL      | 1             | 3       |
|100    | 2014-08-03    | NULL      | 0             | 0       |
|101    | 2014-08-04    | NULL      | 0             | 0       |
|102    | 2014-08-05    | NULL      | 1             | 1       |
|103    | 2014-08-06    | NULL      | 1             | 2       |
|104    | 2014-08-07    | Sunday    | NULL          |         |
|105    | 2014-08-08    | NULL      | 1             | 3       |
|106    | 2014-08-09    | NULL      | 1             | 4       |
|107    | 2014-08-10    | NULL      | 1             | 5       |
|-------------------------------------------------------------|

这是我到目前为止所做的。对我来说,星期日也会逐渐增加。 任何帮助,解决它..

SQL

SELECT  X.*, X.ID - LU.FROMID + 1
FROM    @TAB X LEFT JOIN
        (
        SELECT  (SELECT MIN(ID) FROM @TAB) FROMID,MIN(ID) TOID FROM @TAB WHERE ATTENDANCE = 0 
        UNION
        SELECT  A.ID FROMID,B.ID TOID 
        FROM    (SELECT ID,ROW_NUMBER() OVER (ORDER BY ID) R FROM @TAB WHERE ATTENDANCE = 0) A CROSS JOIN
                (SELECT ID,ROW_NUMBER() OVER (ORDER BY ID) R FROM @TAB WHERE ATTENDANCE = 0) B 
                WHERE A.R = (B.R - 1)
        UNION
        SELECT  MAX(ID),(SELECT MAX(ID) FROM @TAB) FROM @TAB WHERE ATTENDANCE = 0 
        UNION
        SELECT  MAX(ID),MAX(ID) + 1 FROM @TAB
        ) LU
ON      X.ID >= LU.FROMID AND X.ID < LU.TOID

测试的来源数据:

SET DATEFORMAT DMY
DECLARE @TAB TABLE (ID INT IDENTITY(89,1),DT DATE,DAY VARCHAR(15),ATTENDANCE BIT)
INSERT INTO @TAB VALUES
('23-08-2014',Null,1),
('24-08-2014','Sunday',Null ),
('25-08-2014',Null ,1),
('26-08-2014',Null ,1),
('27-08-2014',Null ,0),
('28-08-2014',Null ,1),
('29-08-2014',Null ,0),
('30-08-2014',Null ,1),
('31-08-2014','Sunday',Null ),  
('01-08-2014',Null ,1),
('02-08-2014',Null ,1),
('03-08-2014',Null ,0),
('04-08-2014',Null ,1),
('05-08-2014',Null ,0),
('06-08-2014',Null ,1),
('07-08-2014','Sunday',Null ),      
('08-08-2014',Null ,1),
('09-08-2014',Null ,1),
('10-08-2014',Null ,1)

先谢谢。

4 个答案:

答案 0 :(得分:1)

@HHH,我在@TAB周围添加了另一个临时表。这有效,请测试并告诉。

DECLARE @TAB2 TABLE (MASTERID INT IDENTITY(1,1),ID INT,DT DATE,DAY VARCHAR(15),ATTENDANCE BIT)
INSERT INTO @TAB2
SELECT * FROM @TAB WHERE DAY IS NULL

SELECT  Y.*,
        LU2.Streak
FROM    @TAB Y LEFT JOIN (
SELECT  X.ID, X.MASTERID - LU.FROMID + 1 [Streak]
FROM    @TAB2 X LEFT JOIN
        (
        SELECT  (SELECT MIN(MASTERID) FROM @TAB2) FROMID,MIN(MASTERID) TOID FROM @TAB2 WHERE ATTENDANCE = 0 
        UNION
        SELECT  A.MASTERID FROMID,B.MASTERID TOID 
        FROM    (SELECT MASTERID,ROW_NUMBER() OVER (ORDER BY MASTERID) R FROM @TAB2 WHERE ATTENDANCE = 0) A CROSS JOIN
                (SELECT MASTERID,ROW_NUMBER() OVER (ORDER BY MASTERID) R FROM @TAB2 WHERE ATTENDANCE = 0) B 
                WHERE A.R = (B.R - 1)
        UNION
        SELECT  MAX(MASTERID),(SELECT MAX(MASTERID) FROM @TAB2) FROM @TAB2 WHERE ATTENDANCE = 0 
        UNION
        SELECT  MAX(MASTERID),MAX(MASTERID) + 1 FROM @TAB2
        ) LU
ON      X.MASTERID >= LU.FROMID AND X.MASTERID < LU.TOID ) LU2
ON      Y.ID = LU2.ID

结果:

enter image description here

答案 1 :(得分:1)

像戈登一样,你需要确定连续出勤日的群体。但这是另一个版本..

select 
t.*,
t2.Seq,
(case ATTENDANCE
when 1 then ROW_NUMBER() over (partition by t2.Seq,t.attendance order by t.id) 
when 0 then 0
else null end) Streak
from
@TAB t
outer apply
(select 
    count(1) as Seq
from
    @tab t2
where
    t2.id < t.ID
and
    t2.ATTENDANCE = 0) as t2
order by
t.id

答案 2 :(得分:0)

您需要确定连续出勤日的组。您可以使用row_numbers()方法的差异来执行此操作。从整体row_number()(没有星期天)中减去row_number()出勤率(并且没有星期天)。条纹的差异是恒定的。其余的只是另一个row_number()电话。

这是它的样子:

select t.id, t.dt, t.day, t.attendance,
       (case when t.day = 'Sunday' then NULL
             else row_number() over (partition by attendance, grp order by dt)
        end) as streak
from (select t.*,
             (row_number() over (partition by day order by dt) -
              row_number() over (partition by day, attendance order by dt)
             ) as grp
      from @tab t
     ) t;

答案 3 :(得分:0)

根据您的要求,我认为这个查询会很有用,请更改字段名称和表名。这是一种在表格中计算简单运行总计的一种非常简单的方法......

SELECT a.id,a.dateday,a.dateval,(SELECT SUM(b.hoursday)FROM #temp b 其中b.dateday&lt; = a.dateday)为totalhours 来自#temp a

谢谢