SQL服务器:如何根据两个不同的列合并多行?

SQL Server : how to combine multiple rows based on two different columns?

我的数据类似于:

SId       Program      Term       Year       Grad term     Grad year
-------------------------------------------------------------------
1         P           2          2001          3            2005
1         P           3          2001          3            2005
1         P           2          2002          3            2005
2         M           2          2002          2            2004
2         M           3          2002          2            2004

现在,我可以基于一列合并记录 'date',但在我的情况下,我需要检查年份和学期以确保它们是连续的,然后合并它们。(对于每个年,术语从 1-3)。所以执行查询后,结果应该是:

SID  Program  startterm  startyear  EndTerm   EndYear  Gradterm   Gradyear
--------------------------------------------------------------------------
1       P     2         2001         3     2001        3         2005
1       P     2         2002         2     2002        3         2005
2       M     2         2002         3     2002        2         2004

连续年份和学期的记录合并在一起,程序 P,学期 2,年份 2002 的记录与之前的记录不连续,因此该记录将在单独的行中结束相同的开始学期,开始年份和结束学期,结束年份。非常感谢任何帮助。

检查此查询是否适用于 you.Replace 您的列以及 table 您正在使用的列。

               Select o.Program ,min(o.Term) AS StartTerm,
                 o.year AS StartYear,
                max(Term) AS EndTerm,
                 (Select max(g.year) from #GradProg g where g.[Grad term] = 
                       o.[Grad term] AND  g.Program = o.Program AND g.[Grad 
                  year] = o.[Grad year]) AS EndYear,
                 [Grad term],[Grad year]
               from #GradProg o
              group by   Program ,[Grad term],[Grad year],Year
              order by [Grad year] desc 
 /***This is a raw query which should be optimized using self joins***/     
 Select o.Program ,min(o.Term) AS StartTerm,
 min(o.year) AS StartYear,
 max(Term) AS EndTerm,
max(o.year) AS EndYear,
(Select max(g.year) from #GradProg g where g.[Grad term] = o.[Grad term] 
AND  g.Program = o.Program AND g.[Grad year] = o.[Grad year]) AS EndYear,
[Grad term],[Grad year]
,Iscontinous   
 from 
(
  Select *,
  case when (Select i.Program from #GradProg i where i.Term = t.nextterm and 
  i.Year = t.nexttermyear)  is not null then
   1
  when t.year = (Select max(y.Year) from #GradProg y) and t.Term = (Select 
  max(tm.Term) from #GradProg tm where t.Year = tm.Year)  then 
   1
 else
  0
 end as Iscontinous     
  from 

 (Select * ,

    case o1.Term when 3 then 1 
    else (o1.Term +1) 
    end as nextterm,
    case o1.Term when 3 then o1.Year + 1 
    else (o1.Year) 
    end as nexttermyear    
    from #GradProg o1

  )t
 )o
group by   o.Program ,o.[Grad term],o.[Grad year],
Iscontinous 
order by [Grad year] desc
/*********end *************/

试试这个

    create table #tmp (id int, Program VARCHAR(1),Term INT,[Year] INT,[Grad Term] INT, [Grad year] INT)

    insert into #tmp 
    SELECT 1,'P',2,2001,3,2005
    union 
    SELECT 2,'P',3,2001,3,2005
    union
    SELECT 3,'P',2,2002,3,2005
    union
    SELECT 4,'M',2,2002,2,2004
    union
    SELECT 5,'M',3,2002,2,2004

    ;with cte 
    AS(

        select *,
            RANK() OVER(partition by Program,[Year] order by id,[year],term) as [Minrank],
            RANK() OVER(partition by Program,[Year] order by id desc,[year]desc,term desc) as [Maxrank]
        from #tmp
    )


    select c1.id,c2.Program,c1.term as Startterm,c1.[year] as StartYear,
    c2.term as EndTerm, c2.[Year] As EndYear,c1.[Grad Term],c2.[Grad year] from cte c1
    JOIN cte c2 on c1.Program=c2.program and c1.[year]=c2.[year] and c1.Minrank=c2.[Maxrank]
    WHERE c1.Minrank=1
    order by c1.id


    drop table #tmp

此查询取决于术语列的值,如果值介于 1 和 3 之间,则该查询将起作用。它用于查找连续范围

declare @t table (Id int, Program char(1), Term int, Year int, GradTerm int, GradYear int)
insert into @t
values (1, 'P', 2, 2001, 3, 2005)
    , (2, 'P', 3, 2001, 3, 2005), (3, 'P', 2, 2002, 3, 2005)
    , (4, 'M', 2, 2002, 2, 2004), (5, 'M', 3, 2002, 2, 2004)

select
    ID = row_number() over (order by grp), Program, startterm = min(Term)
    , startyear = min(Year), EndTerm = max(Term), EndYear = max(Year), GradTerm, GradYear
from (
    select
        *, grp = Year * 3 + Term - row_number() over (partition by Program, GradTerm, GradYear order by Year, Term)
    from 
        @t
) t
group by Program, GradTerm, GradYear, grp

输出:

ID  Program  startterm  startyear  EndTerm  EndYear  GradTerm  GradYear
-----------------------------------------------------------------------
1   P        2          2001       3        2001     3         2005
2   P        2          2002       2        2002     3         2005
3   M        2          2002       3        2002     2         2004

编辑:

SID 应该在group by,你也需要把它放在row_number。另外,我在答案中的查询有一些错误。因此,您可能会得到错误的结果。这是正确的版本

declare @t table (SID int, Program char(1), Term int, Year int, GradTerm int, GradYear int)
insert into @t
values (1, 'P', 2, 2001, 3, 2005)
    , (1, 'P', 3, 2001, 3, 2005), (1, 'P', 2, 2002, 3, 2005)
    , (2, 'M', 2, 2002, 2, 2004), (2, 'M', 3, 2002, 2, 2004)

select
    SID, Program, startterm = right(min(val), 1)
    , startyear = left(min(val), 4), EndTerm = right(max(val), 1)
    , EndYear = left(max(val), 4), GradTerm, GradYear
from (
    select
        *, grp = Year * 3 + Term - row_number() over (partition by SID, Program, GradTerm, GradYear order by Year, Term)
        , val = concat(Year, Term)
    from 
        @t
) t
group by SID, Program, GradTerm, GradYear, grp