Sql查询以下情况

时间:2014-09-17 09:55:41

标签: sql

汤姆喜欢运动。每个月他都会休息一会儿,然后玩他最喜欢的运动。他在月内更改了游戏,其更改历史记录显示在表格中。 挑战:汤姆最喜欢的运动是什么?

     Tom Favourite Sports
    ----------------------  
Month   PreviousSport   CurrentSport
JAN     REST            CRICKET
JAN     CRICKET         RUGBY
JAN     RUGBY           VOLLEYBALL
JAN     VOLLEYBALL      FOOTBALL
JAN     FOOTBALL        TENNIS
JAN     TENNIS          RUGBY
FEB     REST            KAYAKING
FEB     KAYAKING        SNOWBOARDING
FEB     SNOWBOARDING    SKATING
FEB     SKATING         RAFTING
FEB     RAFTING         KAYAKING
MAR     REST            RACING
MAR     RACING          GLIDING
MAR     GLIDING         SKYDIVING

输出应为

Month   FirstSport  LastSport
JAN     CRICKET     RUGBY
FEB     KAYAKING    KAYAKING
MAR     RACING      SKYDIVING

更改:对源表进行轻微修改

MTH PREVIOUS_SPORT  CURRENT_SPORT
JAN VOLLEYBALL      FOOTBALL
FEB REST            KAYAKING
MAR REST            RACING
JAN CRICKET         RUGBY
FEB SNOWBOARDING    SKATING
MAR RACING          GLIDING
JAN RUGBY           VOLLEYBALL
FEB SKATING         RAFTING
MAR GLIDING         SKYDIVING
JAN FOOTBALL        TENNIS
FEB RAFTING         KAYAKING
JAN TENNIS          RUGBY
JAN REST            CRICKET

现在如何获得以前的输出?

提前致谢。

2 个答案:

答案 0 :(得分:2)

我刚刚考虑了Table的ID列,我们可以避免它和它将Jan / Feb / March转换为Month Numbers&继续没有ID列。但是为了快速回复,就是这样!!!

Select Main.[Month],F.CurrentSport,L.CurrentSport from 
(
    Select a.[Month],min(r) fSport ,max(r) lSport from 
        (select * ,ROW_NUMBER() over (Partition by Month order by ID) as R
            from Tom

        )a
    group by a.[Month]
)as Main    
inner join
    (
        select *, ROW_NUMBER() over (Partition by Month order by ID) as R
        from Tom
    )as F on F.R = Main.fSport and f.[Month] = Main.[Month]
inner join
    (
        select *, ROW_NUMBER() over (Partition by Month order by ID) as R
        from Tom
    )as L on L.R = Main.lSport and L.[Month] = Main.[Month]
order by F.ID

请参阅小提琴演示HERE

另一个变体,多次避免ROW_Number&使用CTE。我认为这应该比以前更快。

;With CTE as
(
select ID,[Month] as M,CurrentSport as Sport 
    , ROW_NUMBER() over (Partition by Month order by ID) as R
from Tom
), CTE1 as 
(
Select M, Min(R) as FS ,Max(R) as LS from  CTE
group by M
)
Select CTE1.M,F.Sport as First,L.Sport as Last from CTE1
inner join CTE as F on F.R = CTE1.FS and F.M = CTE1.M
inner join CTE as L on L.R = CTE1.LS and L.M = CTE1.M
order by L.ID asc

见DEMO HERE

答案 1 :(得分:0)

我认为我们不需要ID列。我们可以使用RowNumber。

所以它应该是这样的:

SELECT Mintmp.mnth, 
       Mintmp.currentsport AS FirstSport, 
       MaxTmp.currentsport AS CurrentSport 
FROM   (SELECT Row_number() 
                 OVER( 
                   partition BY mnth 
                   ORDER BY mnth) AS RowNum, 
               * 
        FROM   @T1) MinTmp 
       INNER JOIN (SELECT Min(rownum) AS MinRow, 
                          mnth, 
                          Max(rownum) AS MaxRow 
                   FROM   (SELECT Row_number() 
                                    OVER( 
                                      partition BY mnth 
                                      ORDER BY mnth) AS RowNum, 
                                  * 
                           FROM   @T1) tmp 
                   GROUP  BY mnth) grpTable 
               ON grpTable.minrow = MinTmp.rownum 
                  AND grpTable.mnth = MinTmp.mnth 
       INNER JOIN (SELECT Row_number()
                            OVER( 
                              partition BY mnth 
                              ORDER BY mnth) AS RowNum, 
                          * 
                   FROM   @T1) MaxTmp 
               ON Maxtmp.rownum = grpTable.maxrow 
                  AND Maxtmp.mnth = grpTable.mnth