Получите первую запись из таблицы 2, где метка времени больше, чем метка времени в таблице 1

#sql #sql-server #tsql

Вопрос:

У меня есть два столика.

EVENT_NARATIVE
EventNum
след.
Сообщение
Время сообщения
ИСТОРИЯ КЛАССА
EventNum
Класс
Время смены классов

Таблица EVENT_NARATIVE содержит много данных (миллионы строк), и каждое событие (EventNum) может содержать несколько записей EVENT_NARATIVE.

Таблица GRADE_HISTORY содержит тысячи строк, и каждое СОБЫТИЕ может иметь несколько изменений оценок.

В таблице EVENT_NARATIVE мне нужно найти все записи, в которых СООБЩЕНИЕ ТИПА «КОД установлен в%» Содержит только одно СООБЩЕНИЕ, соответствующее этому критерию для каждого СОБЫТИЯ.

Как только у меня появятся эти записи, мне нужно будет найти первую ОЦЕНКУ из таблицы GRADE_HISTORY, которая появляется после Message_Time.

Результат должен выглядеть так

EventNum, Сообщение, Message_Time, Оценка, GradeChangeTime

Мой SQL выглядит так, но я знаю, что он не работает

 SELECT 
N.EventNum, N.SEQ, N.MESSAGE_TIME, N.MESSAGE,
G.CHANGE_DATE, G.GRADE
FROM 
    (SELECT EventNum, SEQ, MESSAGE_TIME, MESSAGE 
     FROM  EVENT_NARRATIVE 
     Where MESSAGE LIKE 'CODE set to%' ) N
Left JOIN   (SELECT Top 1 
             Event_Num, CHANGE_DATE, GRADE
             FROM  GRADE_HISTORY) G
ON G.Event_Num = N.Event_Num
AND G.CHANGE_DATE >= N.MESSAGE_TIME
 

SQL-это не моя повседневная работа, поэтому я ценю любую помощь, чтобы получить нужный мне результат.

ПРИМЕР ДАННЫХ
EVENT_NARATIVE

 *EventNum         SEQ        MESSAGE_TIME                  MESSAGE*
000001-01012021   20770236   2021-01-01 00:03:36.0000000   CODE set to 6D02
000001-01022020   8339846    2020-02-01 00:06:14.0000000   CODE set to 17B01
000001-01022021   22038639   2021-02-01 00:04:44.0000000   CODE set to 17A02
 

ПРИМЕРНЫЕ ДАННЫЕ
GRADE_HISTORY

 *EventNum         CHANGE_DATE                       GRADE*
000001-01012021   2021-01-01 00:03:15.0000000       2
000001-01012021   2021-01-01 00:03:37.0000000       3
000001-01012021   2021-01-01 00:03:40.0000000       5
000001-01022020   2020-02-01 00:06:10.0000000       2
000001-01022020   2020-02-01 00:06:15.0000000       2
000001-01022020   2020-02-01 00:06:18.0000000       5
000001-01022020   2020-02-01 00:06:20.0000000       5
000001-01022021   2021-02-01 00:04:40.0000000       2
000001-01022021   2021-02-01 00:04:42.0000000       3
000001-01022021   2021-02-01 00:04:44.0000000       0
000001-01022021   2021-02-01 00:04:54.0000000       5
 

ожидаемый результат

 *EventNum         SEQ        CHANGE_DATE                        GRADE*
000001-01012021   20770236   2021-01-01 00:03:37.0000000        3  
000001-01022020   8339846    2020-02-01 00:06:15.0000000        2
000001-01022021   22038639   22021-02-01 00:04:44.0000000       0
 

Комментарии:

1. Покажите нам некоторые примеры табличных данных и ожидаемый результат — все в виде форматированного текста, а не изображений.

2. Я постараюсь, извините, не очень уверенно с StackOverflow.

3. Без проблем. Помните, что чем проще вы нам поможете, тем лучшие ответы вы получите!

4. Каков наилучший способ вставки образцов данных. Извините за мою тупость

5. @cramar просто создайте таблицу для вставки образцов данных и покажите свой вывод

Ответ №1:

Попробуйте выполнить этот запрос

 SELECT 
    N.EventNum, 
    N.SEQ, 
    N.MESSAGE_TIME, 
    N.MESSAGE,
    G.CHANGE_DATE, 
    G.GRADE
FROM 
(
    SELECT EventNum, SEQ, MESSAGE_TIME, MESSAGE 
    FROM  EVENT_NARRATIVE 
    WHERE MESSAGE LIKE 'CODE set to%' 
) AS N
OUTER APPLY (
    SELECT TOP 1 
        T.CHANGE_DATE,
        T.GRADE
    FROM GRADE_HISTORY AS T
    WHERE T.EventNum = N.EventNum AND T.CHANGE_DATE > N.MESSAGE_TIME
    ORDER BY T.CHANGE_DATE ASC
) AS G
 

Комментарии:

1. Я только что протестировал небольшой набор данных, и он отлично работает — большое спасибо @April Rain. Я также наклонился к чему — то новому-Внешнему…

Ответ №2:

вы можете использовать функцию окна

 SELECT EventNum,SEQ,CHANGE_DATE,GRADE
FROM
    (SELECT 
      N.EventNum,
      N.SEQ,
      G.CHANGE_DATE,
      G.GRADE,ROW_NUMBER() OVER(PARTITION BY N.EventNum ORDER BY (SELECT null)) AS NUM
    FROM EVENT_NARATIVE N 
    JOIN GRADE_HISTORY G ON N.EventNum = G.EventNum
    WHERE G.CHANGE_DATE >= N.MESSAGE_TIME AND N.MESSAGE LIKE 'CODE set to%') T
WHERE NUM = 1
 

демонстрация в бд<>скрипка<>