计算组内的行差

时间:2019-03-18 17:09:33

标签: sql-server

我正在寻求有关计算SQL(Microsoft SQL Server)组中连续有序行之间差异的帮助。

我有一张这样的桌子:

ID   School_ID   Enrollment_Start_Date   Order
1        56            1/1/2018            10
1        56            5/5/2018            24
1        56            7/7/2018            35  
1       103            4/4/2019            26
1       103            3/3/2019            19

我想计算订购,分组依据 ID,学校ID和订购依据注册日期之间的差异。

所以我想要这样的东西:

ID   School_ID   Enrollment_Start_Date   Order  Diff
1        56            1/1/2018            10    10 # nothing to be subtracted from 10
1        56            5/5/2018            24    14 # 24-10
1        56            7/7/2018            35    11 # 35-24
1       103            3/3/2019            19    19 # nothing to be subtracted from 19
1       103            4/4/2019            26    7 # 26-19

我有数百个ID,每个ID最多可以有6个Enrollment_Start_Date,因此我正在寻找一些可概括的实现。

3 个答案:

答案 0 :(得分:2)

使用LAG(<column>)分析函数获得在OVER部分中指定的“上一个”列值,然后从中减去当前值,并使其为正数乘以-1。如果以前的值不存在(为null),则取当前值。

伪代码为:

If previous_order_value exists:
  -1 * (previous_order_value - current_order_value)
Else
  current_order_value

其中previous_order_value基于相同的ID和school_id,并按enrollment_start_date升序排序

SQL代码:

select
    id,
    school_id,
    enrollment_start_date,
    [order],
    coalesce(-1 * (lag([order]) over (partition by id, school_id order by enrollment_start_date ) - [order]), [order]) as diff
from yourtable

还请注意,order关键字在SQL Server中是保留的,这就是为什么您创建的列的名称包含在[ ]中的原因。如果可能,我建议在此列中使用其他词语。

答案 1 :(得分:1)

使用lag()分析函数获取两行之间的差异,并获取不存在差异的订单列原始值的情况

    with cte as
(
select 1 as id, 56 as sclid, '2018-01-01' as s_date, 10 as orders
union all
select 1,56,'2018-05-05',24 union all
select 1,56,'2018-07-07',35 union all
select 1,103,'2019-04-04',26 union all
select 1,103,'2019-03-03',19 
) select t.*, 
case when ( lag([orders])over(partition by id,sclid order by s_date ) -[orders] )
 is null then [orders] else
  ( lag([orders])over(partition by id,sclid order by s_date ) -[orders] )*(-1) end
  as diff
 from cte t

输出

id  sclid   s_date   orders diff
1    56   2018-01-01    10  10
1    56   2018-05-05    24  14
1    56   2018-07-07    35  11
1    103  2019-03-03    19  19
1   103   2019-04-04    26  7

demo link

答案 2 :(得分:0)

使用LAG(COLUMN_NAME)

查询

SELECT id, School_ID, Enrollment_Start_Date, cOrder,
ISNULL((cOrder - (LAG(cOrder) OVER(PARTITION BY id, School_ID ORDER BY Enrollment_Start_Date))),cOrder)Diff
FROM Table1

样本输出

| id | School_ID | Enrollment_Start_Date | cOrder | Diff |
|----|-----------|-----------------------|--------|------|
|  1 |        56 |            2018-01-01 |     10 |   10 |
|  1 |        56 |            2018-05-05 |     24 |   14 |
|  1 |        56 |            2018-07-07 |     35 |   11 |
|  1 |       103 |            2019-03-03 |     19 |   19 |
|  1 |       103 |            2019-04-04 |     26 |    7 |

SQL Fiddle Demo