Question

I have two tables that aren't really associated, but need to be combined. So I'm using union all on the two tables. The unioned tables are ordered by date, so rows from one table are dispersed among rows from the other table. What I need to do is get a running count of a column so I can group elements.

To explain further, table A holds dates of when a container is emptied, while table B holds daily entries for content of the container. I need to union the two tables so I have one table where I can get the sum of the information for a container before the container is emptied.

So I need something like this:

Table A:

Location_ID     Empty Date
123             3/2/13
123             3/10/13
123             4/1/13

Table B:

PSI             Entry Date      Location_ID
120             2/28/13         123 (same for all)
130             3/1/13 
100             3/8/13
110             3/9/13
200             3/18/13
180             3/20/13

So the unioned table after some magic would look like:

Table C...:

Location_ID     Date        PSI      Emptied   
123             2/28/13     120      0
123             3/1/13      130      0
123             3/2/13      null     1
123             3/8/13      100      0
123             3/9/13      110      0
123             3/10/13     null     1
123             3/18/13     200      0
123             3/20/13     180      0
123             4/1/13      null     1

What I need to do is have a grouping such that I can have a table like this

Table C_b

Location_ID     Date        PSI      Emptied   Group
123             2/28/13     120      0         1
123             3/1/13      130      0         1
123             3/2/13      null     1         1
123             3/8/13      100      0         2
123             3/9/13      110      0         2
123             3/10/13     null     1         2
123             3/18/13     200      0         3
123             3/20/13     180      0         3
123             4/1/13      null     1         3

How can I get that grouping in that way? I have to make it work in SQL Server 2008. I have tried using Count, and Rank, and Row_Number. But the problem with those is that it won't do a running count, it will just say the total count in each row.

Was it helpful?

Solution

Try this query:

DECLARE @MyTable TABLE(
EntryDate DATE NOT NULL,
Emptied BIT NOT NULL
);
INSERT INTO @MyTable (EntryDate,Emptied)
VALUES 
('2013-01-01',0),
('2013-01-02',0),
('2013-01-03',1),
('2013-01-04',0),
('2013-01-05',0),
('2013-01-06',1),
('2013-01-07',0),
('2013-01-08',0),
('2013-01-09',1);

DECLARE @TableWithRowNum TABLE(
EntryDate DATE NOT NULL,
Emptied BIT NOT NULL,
RowNum INT PRIMARY KEY
);
INSERT INTO @TableWithRowNum (EntryDate,Emptied,RowNum)
SELECT  crt.*,ROW_NUMBER() OVER(ORDER BY crt.EntryDate) AS RowNum
FROM    @MyTable crt;

WITH RecCTE
AS(
    SELECT  
        crt.EntryDate,
        crt.Emptied,
        crt.RowNum,
        1 AS Grp
    FROM    @TableWithRowNum crt
    WHERE   crt.RowNum=1
    UNION ALL
    SELECT  
        crt.EntryDate,
        crt.Emptied,
        crt.RowNum,
        CASE WHEN prev.Emptied=1 THEN prev.Grp+1 ELSE prev.Grp END
    FROM    @TableWithRowNum crt INNER JOIN RecCTE prev ON crt.RowNum=prev.RowNum+1
)
SELECT * FROM RecCTE 
OPTION(MAXRECURSION 0); -- Default value for MAXRECURSION is 100
GO

Results:

EntryDate  Emptied RowNum Grp
---------- ------- ------ ---
2013-01-01 0       1      1
2013-01-02 0       2      1
2013-01-03 1       3      1
2013-01-04 0       4      2
2013-01-05 0       5      2
2013-01-06 1       6      2
2013-01-07 0       7      3
2013-01-08 0       8      3
2013-01-09 1       9      3
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top