2012-09-18 6 views
6

Mi tabla es una lista de programas de TV programados para varios días y canales.Información del programa de TV actual y siguiente Consulta SQL

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 

El conjunto de resultados que intento crear es Qué está pasando ahora y Qué hay a continuación.

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

Así que algo como:

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

he estado devanando los sesos a la mejor manera de hacer esto sin tener que codificar una consulta individual para cada canal. Creo que ahora tengo el pensamiento excesivo en el escenario , así que sería genial si alguien puede señalarme en la dirección correcta.

Gracias

PD: Si se hace una diferencia Estoy en Microsoft SQL Server 2012

Respuesta

3

Esto realmente parece ser algo que le gustaría a su formato GIU y pivotear, pero aquí está mi intento.

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 

Editar: sólo estoy usando el tiempo aquí, pero sólo tiene que añadir la fecha. Deberías considerar combinar las columnas de fecha y hora.

Edit2: Para agregar la fecha simplemente reemplace la hora de comparar con esto. Incluso debería funcionar sobre los límites de la fecha.

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

Brillante! Muchas gracias! Sin embargo, tengo una columna de fecha/hora combinada que es para el tiempo de transmisión "real", no para la hora/fecha del estilo de la guía de TV que estoy usando aquí. (Por ejemplo: 18:00:00 vs 18:02:13) Además, estoy de acuerdo en que algo de esto podría hacerse en la GUI, pero sabía que se podía hacer en SQL y eso me estaba volviendo loco. Gracias – 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 

Yo no lo he probado (debido a la falta de disponibilidad de SQL Server en este punto), pero esto Deberia trabajar.

+0

No se puede seleccionar '2' superior en contexto escalar – Andomar

+0

Gracias, sino que también no le gustaba el orden de salida que contiene con Título en algún tipo de agregado. – pugu

0

Para obtener los datos y la tabla cruzada, utilice lo siguiente. Puede cambiar el nombre de las columnas del canal en la primera selección, pero debe especificar los canales válidos en la lista dinámica.

N.b. El código podría simplificarse combinando los campos de fecha y hora con un solo campo de fecha y hora.

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

Gracias, voy a experimentar con este código también. – pugu

+0

Saludos, esto funciona en todos los casos solo se ve un poco feo porque lo hice sin CTE o RANK() por alguna razón! –

2

Aquí está el SQLFiddle example. Esta consulta también funciona bien si un programa se inicia el día anterior y finaliza en el actual o se inicia en el actual y finaliza el día siguiente (para los resultados NOW y NEXT).

Por fecha actual basta con sustituir cast('09/19/2012 07:15' as datetime) con el 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

El ejemplo anterior de Magnuses no puede manejar el 'próximo' programa si está en el límite de fecha como lo he implementado, por lo que se jugará más y consultará su código. – pugu

0

Otra opción posible - el cálculo de la diferencia de tiempo & buscar el valor más pequeño + ve (al lado) y el menor valor -ve (ahora) - asume FECHA & campos de tipo TIME, también devuelve minutos desde el inicio/hasta el inicio.

;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 
Cuestiones relacionadas