计算每个ID列的值更改

时间:2014-01-29 18:35:48

标签: sql-server-2008 tsql count group-by

我的数据如下:

ID   | DateFrom   | Value1 
###########################
1    | 01/01/2012 | VAL1   
1    | 01/15/2012 | VAL1   
1    | 06/01/2013 | VAL2   
1    | 01/01/2014 | VAL3   
2    | 01/01/2012 | VAL1   
2    | 01/15/2012 | VAL1   
2    | 06/01/2013 | VAL1   
3    | 01/01/2012 | VAL2   
3    | 01/15/2012 | VAL2   
3    | 06/01/2013 | VAL1 

我希望按Value1进行分组,并计算该值“丢失”和ID的次数以及该值“获得”ID的次数。

示例:ID 1

首先它在06/01/2013从VAL1变为VAL2(VAL1丢失1,VAL2升1)

然后它在2014年1月1日从VAL2变为VAL3(VAL2丢失1且VAL3获得1)

我希望运行这样的所有数据,并总计丢失的ID数和每个Value1获得的ID总数。像这样:

Value1   | ID Gain   | ID Lost 
###########################
VAL1     | 1         | 1   
VAL2     | 1         | 1 
VAL3     | 1         | 0 

希望你们都能帮助我!

2 个答案:

答案 0 :(得分:0)

你可以试试这个

WITH t AS (
  SELECT 
    [ID], [DateFrom], [Value1]
     , ROW_NUMBER() OVER (ORDER BY ID,DateFrom) AS row_num
  from tbl
)
, cal AS (
SELECT t1.ID, t1.Value1 as ValueFrom, t2.Value1 AS ValueTo
FROM t t1 
INNER JOIN t t2
  ON t2.row_num = t1.row_num +1
WHERE t1.Value1 <> t2.Value1
)
SELECT
  Value,
  SUM(Gain) As IDGain,
  SUM(Lost) AS IDLost
FROM
(
  SELECT ValueFrom AS Value, 0 AS Gain, 1 as Lost
  FROM cal
  UNION ALL
  SELECT ValueTo AS Value, 1 as Gain, 0 AS Lost
  FROM cal
) a
GROUP BY Value

SQL Fiddle

答案 1 :(得分:0)

-- Source Data
declare @Src table ( id int, datefrom date, value1 nvarchar(4))

insert @Src
select * from 
(values
   (1    , '01.01.2012' , 'VAL1' ),  
   (1    , '15.01.2012' , 'VAL1'   ),
   (1    , '01.06.2013' , 'VAL2'   ),
   (1    , '01.01.2014' , 'VAL3'   ),
   (2    , '01.01.2012' , 'VAL1'   ),
   (2    , '15.01.2012' , 'VAL1'   ),
   (2    , '01.06.2013' , 'VAL1'   ),
   (3    , '01.01.2012' , 'VAL2'   ),
   (3    , '15.01.2012' , 'VAL2'   ),
   (3    , '01.06.2013' , 'VAL1' ) ) T ( ID, Date, Value )

 ;


WITH t AS (
  SELECT 
    id, datefrom, value1
      ,ROW_NUMBER() OVER (partition by id ORDER BY datefrom,value1) as rn 
  from @SRC
)
, cnts AS (
select value1 = a1.value1,cnt1 = count(*) over ( partition by A1.value1) , value2 = A.Value1,cnt2 =  count(*) over ( partition by A.value1)
from t A
right join t A1 on A1.id = A.ID and A1.rn = A.rn + 1 
where isnull(A.value1,'') <> A1.value1
),
Gain as ( 
select distinct value1,cnt1 from Cnts
),
Loss as (
select distinct value2,cnt2 from Cnts
)
SELECT 
Value = g.value1,
gain = g.cnt1,
loss = isnull(l.cnt2,0)

 from gain g left join loss l
 on g.value1 = l.value2


/*   yield result 

Value   gain    loss
VAL1    3   1
VAL2    2   2
VAL3    1   0

*/