У меня есть таблица (назовем ее audit
), который выглядит следующим образом:Выберите самую низкую дату из диапазона и исключить другой диапазон
+--------------------------------------------------------------------------+
| id | recordId | status | mdate | type | relatedId |
+--------------------------------------------------------------------------+
| 1 | 3006 | A | 2013-04-03 23:59:01.275 | type1 | 1 |
| 2 | 3025 | B | 2013-04-04 00:00:02.134 | type1 | 1 |
| 3 | 4578 | A | 2013-04-04 00:04:30.033 | type2 | 1 |
| 4 | 7940 | C | 2013-04-04 00:04:32.683 | type1 | <NULL> |
| 5 | 3006 | D | 2013-04-04 00:04:32.683 | type1 | <NULL> |
| 6 | 4822 | E | 2013-04-04 00:04:32.683 | type2 | <NULL> |
| 7 | 3006 | A | 2013-04-04 00:06:54.033 | type1 | 2 |
| 8 | 3025 | C | 2013-04-04 00:06:54.033 | type1 | 2 |
... и для миллионов строк. И еще один стол мы будем называть related
:
+-------------+
| id | source |
+-------------+
| 1 | src_X |
| 2 | src_Y |
| 3 | src_Z |
| 4 | src_X |
| 5 | src_X |
... и на протяжении сотен тысяч строк.
На обеих таблицах больше столбцов, но это все, что нам нужно для описания проблемы. Столбец relatedId
присоединяется к таблице related
. recordId
также присоединяется к другой таблице и будет содержать несколько записей в audit
с тем же recordId
.
Я пытаюсь создать запрос, который будет производить следующий вывод:
+-----------------+
| source | count |
+-----------------+
| src_X | 1643 |
| src_Y | 255 |
| NULL | 729 |
+-----------------+
Количество является количество записей в audit
, которые данный type
(например "type1"
.) И в наборе статусов (например, "A", "B", "C"
), которые затем оставлены внешними, соединенными с related
и сгруппированы по source
.
Загвоздка в том, что я только хочу, чтобы включать записи изнутри audit
, которые находятся в пределах определенного диапазона дат, и я только хочу, чтобы присоединиться от audit
к related
на самой старой записи в пределах этого диапазона для каждого recordId
. Кроме того, я хочу игнорировать любые записи, которые соответствуют критериям type
и status
, но имеют запись для того же recordId
, что старше, чем диапазон дат.
Таким образом, чтобы выяснить, из приведенного выше примера данных: Допустим, я хочу, тип type1
и значения из "A", "B", "C"
с диапазона дат 2013-04-04
к 2013-04-05
. Строки 2 и 4 будут включены в счет. Строка 3 исключается, так как она имеет неправильный type
. Строка 5 исключается, так как статус неверен. Строка 6 исключается из-за неправильного состояния и типа. Строка 1 исключается, так как она находится за пределами диапазона дат. Строка 7 также исключается, так как существует еще одна строка (строка 1), которая соответствует критериям статуса и типа с тем же recordId
, который старше начала диапазона дат. Строка 8 исключается, так как и строка 8, и строка 2 имеют одинаковые recordId
и соответствуют критериям, но мы учитываем только самую старую запись двух в пределах диапазона.
Другими словами, я хочу считать только в первый раз, когда запись для данного recordId появляется в таблице и находится в пределах диапазона заданных дат.
Мы придумали следующее:
WITH data (recordId, id) AS (
SELECT a.recordId, MIN(a.id)
FROM audit a
WHERE a.status in ('A','B','C')
AND type = 'type1'
GROUP BY a.recordId
)
SELECT r.source, COUNT(*)
FROM data d
JOIN audit a ON d.id = a.id
LEFT JOIN related r ON a.relatedId = r.id
WHERE a.mdate >= '2013-04-04 00:00:00.000'
and a.mdate < '2013-04-05 00:00:00.000'
GROUP BY r.source
Это будет работать на MSSQL Server 2008, и в настоящее время основывается на том факте, что таблица аудита идентификаторы являются автогенерируемые. Поскольку идентификаторы генерируются в точке, в которую вставлена запись, а mdate также является временной меткой вставки, и записи никогда не обновляются после вставки, я думаю, что это нормально. Похоже, что запрос дает правильный результат по ограниченному набору тестовых данных, но я надеялся на второе мнение.
- Этот вопрос выглядит нормально?
- Можно ли улучшить его производительность?
Диапазон дат в выраженном выражении таблицы, вероятно, улучшит производительность. –
Хорошая точка. Добавление 'AND a.mdate <'2013-04-05 00: 00: 00.000'' в вычисленную таблицу поможет ограничить количество возвращаемых записей. –
Чтобы улучшить производительность запросов, позаботьтесь об индексировании. Используйте индексирование в полях WHERE Clause, Join Fields и снова проверьте производительность. –