【问题标题】:Removing duplicates from Join with grouped result使用分组结果从 Join 中删除重复项
【发布时间】:2020-02-27 06:55:17
【问题描述】:

我使用带有 EF Core 的 sql 服务器。由于 EF 缺乏 GROUP BY 支持,我运行原始 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

但如果我想在最终结果中添加一个记录 ID (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) 记录?

【问题讨论】:

    标签: sql sql-server entity-framework-core


    【解决方案1】:

    我只会使用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()

    【讨论】:

      猜你喜欢
      • 2019-01-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-01
      • 2021-07-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多