2012-09-18 12 views
6

Moja tabela zawiera listę zaplanowanych programów telewizyjnych na wiele dni i kanałów.Informacje o programie telewizyjnym o aktualnych i następnych programach zapytania SQL Zapytanie o numer

SELECT * FROM [Scheduled_Programmes] 

Channel Date   Time  Title 
1   2012-09-19 06:00 Family Guy 
2   2012-09-19 06:01 CSI Miami 
3   2012-09-19 06:20 News 
1   2012-09-19 06:30 Heroes 
2   2012-09-19 07:01 Spiderman 
3   2012-09-19 06:40 Batman 
1   2012-09-19 07:30 Micky Mouse 
2   2012-09-19 07:31 CSI New York 
3   2012-09-19 07:10 Friends 
1   2012-09-19 07:55 The Wire 
2   2012-09-19 08:00 Dodgeball 
3   2012-09-19 07:35 Gossip Girl 

Zestaw wyników, który próbuję utworzyć, to funkcja Co teraz i co dalej.

Let's assume the current datetime is (D/M/Y HH:MM) 19/09/2012 07:15 

Więc coś takiego:

  Channel 1  Channel 2  Channel 3 
NOW  Heroes  Spiderman  Friends 
NEXT  Micky Mous CSI New York Gossip Girl 

Byłem regały mój mózg za najlepszy sposób to zrobić bez konieczności ciężkiej kodu indywidualnego zapytania dla każdego kanału. Myślę, że mam przemyślenie tego etapu teraz , więc byłoby wspaniale, gdyby ktoś mógł wskazać mi właściwy kierunek.

Dzięki

PS: Jeśli to robi różnicę jestem na Microsoft SQL Server 2012

Odpowiedz

3

To naprawdę wydaje się jak coś, co pozwoliłoby na twój format GIU i przestawne, ale tutaj jest moja decyzja.

SELECT * FROM (
    SELECT * FROM (
     SELECT X.Status, X.Channel, X.Title FROM (
     SELECT 'NOW' as Status, Channel, Title, RANK() OVER (PARTITION BY Channel ORDER BY Time DESC) RANKED FROM Sceduled_Programs SP 
     WHERE DateTime <= '7:15') X 
     WHERE X.RANKED = 1 
    ) A 
    UNION ALL 
     SELECT * FROM (
     SELECT Y.Status, Y.Channel, Y.Title FROM (
     SELECT 'NEXT' as Status, Channel, Title, RANK() OVER (PARTITION BY Channel ORDER BY Time ASC) RANKED FROM Sceduled_Programs SP 
     WHERE DateTime > '7:15') Y 
     WHERE Y.RANKED = 1 
    ) B 
) DataToPivot 
PIVOT (MAX(Title) FOR Channel IN ([1], [2], [3])) AS PivotTable 

Edit: Ja tylko używając czasu tutaj, ale wystarczy dodać datę. Powinieneś naprawdę rozważyć połączenie kolumn daty i czasu.

Edycja2: Aby dodać datę wystarczy wymienić czas porównać z tym. Powinien nawet przekroczyć granice daty.

WHERE CAST(Date AS DATETIME) + CAST(Time AS DATETIME) > '19/09/2012 07:15' 
+0

Genialny! Dziękuję bardzo! Mam połączoną kolumnę daty/czasu, jednak jest to dla "rzeczywistego" czasu transmisji, a nie dla czasu/daty stylu przewodnika telewizyjnego, którego tutaj używam. (np. 18:00:00 vs 18:02:13) Ponadto, zgadzam się, że niektóre z tego można zrobić w GUI, ale wiedziałem, że można to zrobić w SQL i doprowadzało mnie to do szaleństwa. Dzięki – pugu

0
select distinct Channel 
, (
select top 2 Title from 
     (
     select Title 
     from [Scheduled_Programmes] s 
     where s.Channel = o.Channel 
     and Date >='2012-09-19' and Time >='07:15' 
     group by Channel 
     order by Date, Time desc 
     ) x 
) as Prog 
from [Scheduled_Programmes] o 

nie próbowałem go (z powodu niedostępności serwera SQL w tym momencie), ale tym powinno działać.

+0

Nie można wybrać górną '2' w kontekście skalarnym – Andomar

+0

Dzięki, to też nie podoba się zamówienie z zewnątrz zawierające tytuł w pewnego rodzaju kruszywa. – pugu

0

Aby uzyskać dane i tę kartę, użyj następującego polecenia. Możesz zmienić nazwę kolumny kanału w pierwszym wyborze, ale musisz określić prawidłowe kanały na liście przestawnej.

N.b. Kod można uprościć, łącząc pola daty i czasu z pojedynczym polem daty i godziny.

declare @current_date datetime = '20120919 07:15' 

select * 
from (
    select whenon, a1.channel, title from (
    select a.channel, MAX(CAST(Date AS DATETIME) + CAST(Time AS DATETIME)) as DateTime, 'now' as whenon 
    from Scheduled_Programmes a 
    join (
    select channel, MIN(CAST(Date AS DATETIME) + CAST(Time AS DATETIME)) as NextTime 
    from Scheduled_Programmes 
    where CAST(Date AS DATETIME) + CAST(Time AS DATETIME) > @current_date 
    group by channel 
) b on a.channel = b.channel and CAST(Date AS DATETIME) + CAST(Time AS DATETIME) < NextTime 
    group by a.channel 
    union 
    select channel, MIN(CAST(Date AS DATETIME) + CAST(Time AS DATETIME)), 'next' from Scheduled_Programmes where CAST(Date AS DATETIME) + CAST(Time AS DATETIME) > @current_date 
    group by channel 

) a1 
    join Scheduled_Programmes b1 on a1.channel = b1.channel and a1.DateTime = CAST(Date AS DATETIME) + CAST(Time AS DATETIME) 
) sub 
pivot (max(title) for channel in ([1], [2], [3])) pivottable 
order by whenon desc 
+0

Dzięki, eksperymentuję z tym kodem. – pugu

+0

Wiwaty, to działa we wszystkich przypadkach tylko wygląda trochę brzydko, ponieważ zrobiłem to bez CTE lub RANK() z jakiegoś powodu! –

2

Oto SQLFiddle example. To zapytanie działa również, jeśli program rozpoczyna się poprzedniego dnia i kończy w bieżącym lub rozpoczyna się w bieżącym i kończy następnego dnia (dla wyników TERAZ i NASTĘPNYCH).

Dla bieżącej daty prostu zastąpić cast('09/19/2012 07:15' as datetime) z CURRENT_TIMESTAMP:

with T as 
(select channel, title, 
     (date+cast(Time as datetime)) as D_Time 
     from Scheduled_Programmes 
) 

select nn, 
    max(CASE when channel=1 then Title end) as Chanel1, 
    max(CASE when channel=2 then Title end) as Chanel2, 
    max(CASE when channel=3 then Title end) as Chanel3 


from 
(
select 'NOW' nn,Channel,Title,D_time, 
    row_number() over (PARTITION by channel 
         order by D_time desc) rn 
    from T 
    where D_time<=cast('09/19/2012 07:15' as datetime) 
union 
select 'NEXT'nn,Channel,Title,D_time, 
    row_number() over (PARTITION by channel 
         order by D_time asc) rn 
    from T 
    where D_time>cast('09/19/2012 07:15' as datetime) 
) ATable where rn=1 
group by nn 
order by nn desc; 
+0

powyższy przykład Magnuses nie może obsłużyć "następnego" programu, jeśli znajduje się on na granicy daty, ponieważ go zaimplementowałem, więc będzie dalej majstrować i sprawdzać twój kod. – pugu

0

Inna możliwość - oblicza się różnicę czasu & pobierania najmniejszą wartość dodatnią (NEXT) i najmniejszą wartość ve (pory) - zakłada DATA & Pola typu TIME, również zwraca minuty od rozpoczęcia/do rozpoczęcia.

;with T(Channel, Date, Time, Title, delta) as (
select 
    *, 
    datediff(minute, '19 sep 2012 07:15:00', dateadd(day, datediff(day, 0, date), cast(time as datetime2))) 
from 
    Scheduled_Programmes 
) 
select 
case when T.delta >= 0 then 'Next' else 'Now' end, 
T.* 
from T 
inner join (
    select 
     channel, 
     min(case when delta > 0 then delta end) as starts_in, 
     max(case when delta < 0 then delta end) as started 
    from t 
    group by channel 
) T2 
    on T.Channel = T2.Channel and (t.delta = T2.starts_in or t.delta=T2.started) 
order by Channel, delta