2015-07-29 5 views
1

В нижеприведенном ниже запросе создается запись для каждой записи в таблице SP_ScheduleEvent.Ограничение наборов результатов на будущую дату - SQL

SELECT m.MaterialId, m.MaterialTitle, se.EventDateTime, c.ChannelName 
    FROM GB_Material m 
    LEFT OUTER JOIN SP_ScheduleEvent se on se.MaterialName = m.MaterialName 
    INNER JOIN SP_Schedule s on s.ScheduleID = se.ScheduleID 
    INNER JOIN GB_Channel c on c.ChannelID = s.ChannelID 
    WHERE LOWER(m.MaterialName) like '%foo%' OR LOWER(m.MaterialTitle) like '%foo%' 

enter image description here

Я хочу, чтобы ограничить набор результатов в ближайшем будущем EventDateTime.

Так что на имя материала я хотел бы увидеть один EventDateTime, который должен быть ближайшей датой будущего до текущего времени.

И, наконец, запись может не существовать в таблице SP_ScheduleEvent для конкретного materialname, в этом случае должно быть нулевым возвращено для столбца EventDateTime

SQLFiddle

Как бы я идти об этом?

+1

Почему существует два 'SELECT' положения? –

+0

Упс! Ошибка копирования вставки – MrBliz

+1

Ваш вопрос нечеткий и неоднозначный. Вам нужно добавить образцы данных, желаемые результаты, и SQL Fiddle поможет. –

ответ

0

Во-первых, ваш LEFT JOIN несуществен, потому что последующие соединения делают его INNER JOIN. Либо используйте LEFT JOIN по всем операциям FROM или переключитесь на INNER JOIN.

Я думаю, что вы можете использовать ROW_NUMBER():

SELECT t.* 
FROM (SELECT m.MaterialId, m.MaterialName, m.MaterialTitle, se.EventDateTime, 
      ROW_NUMBER() over (PARTITION BY m.MaterialId OVER se.EventDateTime DESC) as seqnum 
     FROM GB_Material m INNER JOIN 
      SP_ScheduleEvent se 
      on se.MaterialName = m.MaterialName INNER JOIN 
      SP_Schedule s 
      on s.ScheduleID = se.ScheduleID INNER JOIN 
      GB_Channel c 
      on c.ChannelID = s.ChannelID 
     WHERE se.EventDateTime > getdate() AND 
      (LOWER(m.MaterialName) like '%foo%' OR LOWER(m.MaterialTitle) like '%foo%') 
    ) t 
WHERE seqnum = 1 
ORDER BY se.EventDateTime; 
+0

Возможно, я должен был быть более ясным в вопросе. Я хочу получить все Materialnames, но только один EventDateTime. Прямо сейчас я получаю все материалы и все EventDateTimes. – MrBliz

+0

Msg 156, Level 15, State 1, Line 3 Неверный синтаксис рядом с ключевым словом 'OVER'. – MrBliz

+0

Я работаю над SQLFiddle – MrBliz

0

Используйте ROW_NUMBER функции():

WITH cte AS (
SELECT m.MaterialId, m.MaterialTitle, se.EventDateTime, c.ChannelName, 
    ROW_NUMBER() OVER (PARTITION BY m.MaterialId ORDER BY EventDateTime ASC) AS rn 
    FROM GB_Material m 
    LEFT OUTER JOIN SP_ScheduleEvent se on se.MaterialName = m.MaterialName 
    LEFT OUTER JOIN SP_Schedule s on s.ScheduleID = se.ScheduleID 
    LEFT OUTER JOIN GB_Channel c on c.ChannelID = s.ChannelID 
    WHERE LOWER(m.MaterialName) like '%foo%' OR LOWER(m.MaterialTitle) like '%foo%' 
    AND se.EventDateTime > GETDATE() 
) 
SELECT * FROM cte 
WHERE rn=1 
+0

Спасибо, я осознал, что мне нужна дополнительная спецификация, касающаяся того, что делать, если в таблице SP_ScheduleEvent нет записи. Обновлен вопрос – MrBliz

+0

Измененный ответ со всеми LOJ для возврата NULL, когда в SP_ScheduleEvent нет записи. –

+0

Оба они дают одинаковые результаты – MrBliz

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