SQL Server:如何基于两个不同的列组合多个行?

时间:2018-04-03 19:57:01

标签: sql-server tsql gaps-and-islands

我的数据类似于:

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

现在,我能够根据一个列'日期'组合记录,但在我的情况下,我需要检查年份和期限,以确保它们是连续的,然后将它们组合。(对于每年,术语从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年的记录与之前的记录不连续,因此记录将以相同的一行结束开始期限,开始年份和结束期限,结束年份。非常感谢任何帮助。

4 个答案:

答案 0 :(得分:1)

检查此查询是否适用于您。使用您正在使用的列替换列和表。

               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 

答案 1 :(得分:1)

此查询取决于术语列的值,如果值介于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

答案 2 :(得分:0)

    public void ConnectMachineIClock(string IP)
    {
        int idwErrorCode = 0;
        var Iclock = IclockDetails.Where(a => a.IpAddress == IP).FirstOrDefault();

        if (AttnMachineRepository.IsMachineOnline(IP) == true)
        {


            Stopwatch sw = Stopwatch.StartNew();
            blnCon = CZKEM1.Connect_Net(IP.Trim(), 4370);
            sw.Stop();
            if (blnCon == true)
            {
                UpdateText(1, txtStatus, Iclock.IpAddress);
                iMachineNumber = Iclock.Id;
                LocId = Iclock.LocationId;
                MType = Iclock.MachineTypeId;
                LocName = AttnMachineRepository.GetPunchLocation(LocId);
                CZKEM1.RegEvent(iMachineNumber, 65535);
                UpdateText(2, txtStatus, Iclock.IpAddress);
                //txtStatus.BeginInvoke((Action)(() => txtStatus.Text += ("Connected with " + Iclock.IpAddress + " " + sw.Elapsed.TotalSeconds + " Seconds taken to connect") + Environment.NewLine));
                MachineIP = Iclock.IpAddress;
                Get_IClock_LogData(iMachineNumber);

            }
            else
            {
                CZKEM1.GetLastError(ref idwErrorCode);
                UpdateText(-1, txtErrorLog, Iclock.IpAddress);
                //txtErrorLog.BeginInvoke((Action)(() => txtErrorLog.Text += "Unable to connect the device with IP: " + MachineIP + ", ErrorCode = " + idwErrorCode.ToString() + "" + Environment.NewLine));
                //Application.DoEvents();
            }
        }
        else
        {
            UpdateText(-2, txtErrorLog, Iclock.IpAddress);
            //txtErrorLog.BeginInvoke((Action)(() => txtErrorLog.Text += "IP " + MachineIP + " not found" + Environment.NewLine));
            //Application.DoEvents();
        }
    }
      public void UpdateText(int status, TextBox text, string IP)
    {
        switch (status)
        {
            case 1:
                text.BeginInvoke((Action)(() => text.Text += ("Data Processing for" + IP + " starts") + Environment.NewLine));
                Application.DoEvents();
                break;
            case 2:
                text.BeginInvoke((Action)(() => text.Text += ("Connected with " + IP) + Environment.NewLine));
                Application.DoEvents();
                break;
            case -1:
                text.BeginInvoke((Action)(() => text.Text += "Unable to connect the device with IP: " + IP + ", ErrorCode = " + -1 + "" + Environment.NewLine));
                Application.DoEvents();
                break;
            case -2:
                text.BeginInvoke((Action)(() => text.Text += "IP " + IP + " not found" + Environment.NewLine));
                Application.DoEvents();
                break;

        }
    }

答案 3 :(得分:0)

试试这个

    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