2014-09-17 2 views
0

Том любит спорт. Каждый месяц он немного отдыхает и играет в свой любимый вид спорта. Он меняет игру в течение месяца, и история изменений показана в таблице. Задача: Каков первый и последний любимый вид спорта, который играет Том?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 

CHANGE: Незначительные изменения в исходной таблице

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 

Теперь, как я могу получить предыдущий вывод?

Заранее спасибо.

+0

Может быть, я что-то отсутствует, но есть необходимость в сохранении отношения к предыдущему спорта? Как насчет того, чтобы иметь дату и текущий порт? – orjan

ответ

2

Я только что рассмотрел колонку ID для таблицы, мы можем ее избежать & конвертировать янв./Февраль/март в виде числа месяцев & идти без столбца 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 несколько раз & с использованием КТР. Я думаю, что это должно быть быстрее предыдущего.

;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

+0

Спасибо, но на выходе скрипта отсутствует столбец LastSport. – Leo

+0

Спасибо! Я обновил демо, проблема заключалась в том, что я сохранил одинаковое имя столбца для двух последних столбцов. – AK47

+0

Превосходно. Благодарю. – Leo

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 
+0

Прохладный! Спасибо брат. – Leo

Смежные вопросы