根据唯一列获取单行

时间:2014-05-09 17:25:03

标签: sql sql-server tsql

我认为这主要是一个术语问题,我很难解决问题。

我有一个包含几个列的表来管理一些历史日志数据。我感兴趣的两列是时间戳(或Id,因为id是按顺序生成的)和terminalID。

我想提供终端ID列表,只查找最新数据,即每个terminalID的最高ID或时间戳


使用@Danny建议的群组解决方案,以及他引用的其他解决方案

我发现时间差异非常明显,所以我在这里为任何人的FYI发布两个结果。

S1:

SELECT UR.* FROM(
SELECT TerminalID, MAX(ID) as lID 
    FROM dbo.Results
    WHERE TerminalID in (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24)
    GROUP BY TerminalID
) GT left join dbo.Results UR on UR.id=lID

S2

SELECT *
FROM (
   SELECT TOP 100
      Row_Number() OVER (PARTITION BY terminalID ORDER BY Id DESC) AS [Row], *
   FROM dbo.Results
   WHERE TerminalID in (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24)
   ORDER BY Id DESC
) a
WHERE a.row=1

结果是:

S1:

  • CPU时间= 297 ms,经过时间= 343 ms。
  • 查询费用36%
  • 缺少指数影响 - 94%

S2:

  • CPU时间= 562 ms,经过时间= 1000 ms。
  • 查询费用64%
  • 缺少指数影响 - 41%

将缺少的索引添加到解决方案一(仅索引ID,而不是s2,其中多列需要索引),我将查询降低到15毫秒

3 个答案:

答案 0 :(得分:3)

使用TOP关键字:

SELECT TOP 1 ID, terminalID FROM MyTable WHERE <your condition> ORDER BY <something that orders it like you need so that the correct top row is returned>.

答案 1 :(得分:2)

我认为你与GROUP BY走在正确的轨道上。听起来像你想要的:

SELECT TerminalID, MAX(Timestamp) AS LastTimestamp
    FROM [Table_Name]
    WHERE TerminalID IN (.., .., .., ..)
    GROUP BY TerminalID

答案 2 :(得分:1)

虽然不如使用MAX GROUP BY那么明显,但如果您需要有多个列来确定要拉回哪一行,这可以提供额外的灵活性。

SELECT *
FROM (
   SELECT
      Row_Number() OVER (PARTITION BY terminalID ORDER BY Id DESC) AS [Row],
      [terminalID],[Id],[timestamp]
   FROM <TABLE>
   ORDER BY Id DESC
) a
WHERE a.row=1