Удаление дубликатов из Join с группированным результатом - PullRequest
0 голосов
/ 01 ноября 2019

Я использую сервер sql с EF Core. Из-за отсутствия поддержки GROUP BY EF я запускаю необработанный SQL-запрос.

Итак, у меня есть таблица истории

+------------+---------+------------------+
| HardwareId | StateId |    Timestamp     |
+------------+---------+------------------+
| Dev1       |       1 | 2019-10-11 11:00 |
| Dev2       |       2 | 2019-10-11 11:01 |
| Dev1       |       3 | 2019-10-11 11:09 |
| Dev2       |       1 | 2019-10-11 11:10 |
| Dev2       |       2 | 2019-10-11 11:10 |
| Dev1       |       3 | 2019-10-11 11:11 |
+------------+---------+------------------+

Здесь некоторые записи устройства могут иметь одинаковые временные метки.

Теперь я хочу иметь последнее состояние каждого устройства:

+------------+---------+------------------+
| HardwareId | StateId |    Timestamp     |
+-----==-----+---------+------------------+
| Dev2       |       1 | 2019-10-11 11:10 |
| Dev1       |       3 | 2019-10-11 11:11 |
+------------+---------+------------------+

Я запускаю

SELECT H.TimeStamp, H.HardwareId, H.ErrorCode, SD.Description FROM History H
INNER JOIN 
(SELECT HardwareId, MAX(TimeStamp) LastDateTime from History 
GROUP BY HardwareId) AS LastStates 
ON H.TimeStamp = LastStates.LastDateTime
INNER JOIN StateDescription SD ON H.ErrorCode = SD.Id ORDER BY H.HardwareId

, но это дает мне дубликаты (из-за дубликатов меток времени для данного устройства,вид нескольких последних состояний устройства. Я бы предпочел выбрать любое из этих состояний)

+------------+---------+------------------+
| HardwareId | StateId |    Timestamp     |
+------------+---------+------------------+
| Dev2       |       1 | 2019-10-11 11:10 |
| Dev2       |       2 | 2019-10-11 11:10 |
| Dev1       |       3 | 2019-10-11 11:11 |
+------------+---------+------------------+

добавление DISTINCT исправляет его

SELECT DISTINCT H.TimeStamp, H.HardwareId, H.ErrorCode, SD.Description FROM History H
INNER JOIN 
(SELECT HardwareId, MAX(TimeStamp) LastDateTime from History 
GROUP BY HardwareId) AS LastStates 
ON H.TimeStamp = LastStates.LastDateTime
INNER JOIN StateDescription SD ON H.ErrorCode = SD.Id ORDER BY H.HardwareId

, но если я хочу добавить идентификатор записи (H.Id) к окончательному результату я, очевидно, снова получаю дубликаты.

  SELECT DISTINCT H.TimeStamp, H.Id, H.HardwareId, H.ErrorCode, SD.Description FROM History H
    INNER JOIN 
    (SELECT HardwareId, MAX(TimeStamp) LastDateTime from History 
    GROUP BY HardwareId) AS LastStates 
    ON H.TimeStamp = LastStates.LastDateTime
    INNER JOIN StateDescription SD ON H.ErrorCode = SD.Id ORDER BY H.HardwareId

Как я могу получить какую-нибудь TOP (1) запись для каждого устройства?

1 Ответ

0 голосов
/ 01 ноября 2019

Я бы просто использовал row_number():

select h.*
from (select h.*,
             row_number() over (partition by HardwareId order by timestamp desc) as seqnum
      from history h
     ) h
where seqnum = 1;

Это выберет ровно одну строку на устройство в день. Если в день будут дубликаты, он вернет произвольное значение. Если вы хотите все из них, то используйте rank() вместо row_number().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...