获取一行和下一行中的值之间的差异

时间:2014-12-01 07:25:25

标签: sql tsql

我有一些学生在多个报告期内都有报告分数。我使用以下SQL语句来获取这些报告标记

 SELECT DISTINCT ID, thePeriod, MeritRank
 FROM   
 (
 SELECT ID, 
        cast(fileyear as varchar) + cast(filesemester as varchar)  as thePeriod, 
        MeritRank
 FROM uNCStudentMeritList) usm
 ORDER BY ID, thePeriod asc

这给了我以下数据

TableData

我希望有另一列具有每行之间的差异,由ID号分隔。例如

enter image description here

注意:每个StudentId的第一个值项都留空,因为这是他们收到的第一个报告标记。从那时起,我希望看到一个报告标记与下一个报告标记之间的区别。如果他们收到了更糟糕的报告标记,那么它应该是如图所示的负数。我没有行ID号或表中的任何内容 - 我已经看到使用行ID号回答其他类似类型的问题。我怎样才能得到我之后的那种结果>

非常感谢任何帮助。

3 个答案:

答案 0 :(得分:1)

试试这个:

;WITH cte_getdata
     AS (SELECT ID,
                Cast(fileyear AS VARCHAR(10))
                + Cast(filesemester AS VARCHAR(10))                                                    AS thePeriod,
                MeritRank,
                ROW_NUMBER()
                  OVER (
                    partition BY id
                    ORDER BY Cast(fileyear AS VARCHAR(10)) ASC, Cast(filesemester AS VARCHAR(10)) ASC) AS rn
         FROM   uNCStudentMeritList)
SELECT t1.*,
       t1.MeritRank - t2.MeritRank
FROM   cte_getdata t1
       LEFT JOIN cte_getdata t2
              ON t1.rn = t2.rn + 1
                 AND t1.id = t2.id 

Row_Number()函数会为id的分区中的每条记录分配唯一编号,并为fileyear,filesemester的顺序分配唯一编号,然后您可以left join自己的结果集并匹配当前行其前一行具有相同的id。无论匹配条件如何,使用Left Join都会为您提供所有行。以下是两个CTE

的相同方法
;WITH cte1
     AS (SELECT ID,
                Cast(fileyear AS VARCHAR)
                + Cast(filesemester AS VARCHAR) AS thePeriod,
                MeritRank
         FROM   uNCStudentMeritList),
     cte2
     AS (SELECT *,
                ROW_NUMBER()
                  OVER (
                    partition BY ID
                    ORDER BY thePeriod) rn
         FROM   cte1)
SELECT *
FROM   cte2 c1
       LEFT JOIN cte2 c2
              ON c1.id = c2.id
                 AND c1.rn = c2.rn + 1 

答案 1 :(得分:1)

试试这个。

;WITH cte
     AS (SELECT Row_number()OVER (partition BY id ORDER BY theperiod) rn,
                *
         FROM   tablename)
SELECT a.id,
       a.theperiod,
       a.MeritRank,
       a.MeritRank - b.MeritRank
FROM   cte A
       LEFT JOIN cte b
              ON a.rn = b.rn + 1

如果您正在使用SQL SERVER 2012+,请尝试此操作。

SELECT id,
       theperiod,
       MeritRank,
       Lag(MeritRank)
         OVER (
           partition BY id
           ORDER BY theperiod) - MeritRank
FROM   tablename 

答案 2 :(得分:0)

这也应该有效:

SELECT usm1.ID, usm1.thePeriod, usm1.MeritRank, usm2.difference
FROM (SELECT ID, cast(fileyear as varchar) + cast(filesemester as varchar)  as thePeriod, MeritRank
      FROM uNCStudentMeritList)usm1 LEFT OUTER JOIN 
     (SELECT usm3.ID as ID, usm3.thePeriod as thePeriod, max(usm4.thePeriod), (usm3.MeritRank - usm4.MeritRank) as difference 
      FROM (SELECT ID, cast(fileyear as varchar) + cast(filesemester as varchar)  as thePeriod, MeritRank
      FROM uNCStudentMeritList)usm3 JOIN 
      (SELECT ID, cast(fileyear as varchar) + cast(filesemester as varchar)  as thePeriod, MeritRank
      FROM uNCStudentMeritList)usm4 USING (ID) 
      WHERE usm3.thePeriod > usm4.thePeriod
      GROUP BY usm3.ID, usm3.thePeriod)usm2 USING (ID, thePeriod)