#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
демонстрация в бд<>скрипка<>