Microsoft SQL Server:仅返回具有每个唯一ID的最新日期的行
我有一些数据有一个Microsoft SQL Server:仅返回具有每个唯一ID的最新日期的行,sql,sql-server,sql-server-2012,Sql,Sql Server,Sql Server 2012,我有一些数据有一个DeviceID列,一个扫描时间列和一些其他列 对于每个DeviceID,我只想根据扫描时间返回最近的一行 我正在尝试创建此查询,以便将其用作数据的视图和报告 该数据库是Microsoft SQL Server数据库,我正在运行SQL Server 2014 Management Studio中的查询 我能做到的最接近于让它发挥作用的是: SELECT DeviceID, AVSolutionName, DefinitionsUpToDate,
DeviceID
列,一个扫描时间列和一些其他列
对于每个DeviceID,我只想根据扫描时间返回最近的一行
我正在尝试创建此查询,以便将其用作数据的视图和报告
该数据库是Microsoft SQL Server数据库,我正在运行SQL Server 2014 Management Studio中的查询
我能做到的最接近于让它发挥作用的是:
SELECT
DeviceID,
AVSolutionName,
DefinitionsUpToDate,
ScanningEnabled,
Expired,
ScanTime
FROM
dbo.fact_AVSecurity
WHERE
(ScanTime IN (SELECT DISTINCT MAX(ScanTime) AS LastScan
FROM dbo.fact_AVSecurity AS Avs
GROUP BY DeviceID))
不幸的是,这将为同一ID返回多个值
ScanTime ScanningEnabled Expired DeviceID DefinitionsUpToDate AVSolutionName
10/12/2018 10:13 TRUE FALSE 15994 TRUE Webroot SecureAnywhere
4/12/2018 14:30 TRUE TRUE 15994 TRUE Webroot SecureAnywhere
我想要返回的只是最近的第一行:
ScanTime ScanningEnabled Expired DeviceID DefinitionsUpToDate AVSolutionName
10/12/2018 10:13 TRUE FALSE 15994 TRUE Webroot SecureAnywhere
我尝试过不同的方法,比如:
但似乎无法让他们工作。我不确定是我做错了什么,还是我使用的特定品牌的SQL没有做到“第一名”
有没有办法做到我想要的?我与我所拥有的有多接近?检查以下内容:
SELECT t.DeviceID, t.AVSolutionName, t.DefinitionsUpToDate, t.ScanningEnabled, t.Expired, t.ScanTime
FROM dbo.fact_AVSecurity AS t
WHERE t.ScanTime = (SELECT MAX(Avs.ScanTime) FROM dbo.fact_AVSecurity AS Avs WHERE Avs.DeviceID = t.DeviceID)
对于每个DeviceID
获取具有ScanTime=MAX(ScanTime)
的行,请检查以下内容:
SELECT t.DeviceID, t.AVSolutionName, t.DefinitionsUpToDate, t.ScanningEnabled, t.Expired, t.ScanTime
FROM dbo.fact_AVSecurity AS t
WHERE t.ScanTime = (SELECT MAX(Avs.ScanTime) FROM dbo.fact_AVSecurity AS Avs WHERE Avs.DeviceID = t.DeviceID)
对于每个
DeviceID
获取具有ScanTime=MAX(ScanTime)
的行,您接近解决方案。您只需要在相关子查询中做一些更改:
- 在子查询中添加一个
条件,将搜索限制为当前WHERE
DeviceID
- 不需要在子句中使用
来匹配子查询,等式应该是好的,因为无论如何只需要一条记录
- 无需使用
,因为您已经在使用DISTINCT
分组依据
SELECT
t.DeviceID,
t.AVSolutionName,
t.DefinitionsUpToDate,
t.ScanningEnabled,
t.Expired,
t.ScanTime
FROM dbo.fact_AVSecurity AS t
WHERE t.ScanTime =
(SELECT MAX(ScanTime) AS LastScan
FROM dbo.fact_AVSecurity AS Avs
WHERE deviceID = t.deviceID
GROUP BY DeviceID
)
您已接近解决方案。您只需要在相关子查询中做一些更改:
- 在子查询中添加一个
条件,将搜索限制为当前WHERE
DeviceID
- 不需要在子句中使用
来匹配子查询,等式应该是好的,因为无论如何只需要一条记录
- 无需使用
,因为您已经在使用DISTINCT
分组依据
SELECT
t.DeviceID,
t.AVSolutionName,
t.DefinitionsUpToDate,
t.ScanningEnabled,
t.Expired,
t.ScanTime
FROM dbo.fact_AVSecurity AS t
WHERE t.ScanTime =
(SELECT MAX(ScanTime) AS LastScan
FROM dbo.fact_AVSecurity AS Avs
WHERE deviceID = t.deviceID
GROUP BY DeviceID
)
是否将窗口功能与CTE一起使用
With CTE AS (
SELECT t.DeviceID
, t.AVSolutionName
, t.DefinitionsUpToDate
, t.ScanningEnabled
, t.Expired
, t.ScanTime
, Row_Number() over (partition by DeviceID order by scanTime Desc) RN
FROM dbo.fact_AVSecurity t)
SELECT *
FROM CTE
WHERE RN=1
是否将窗口功能与CTE一起使用
With CTE AS (
SELECT t.DeviceID
, t.AVSolutionName
, t.DefinitionsUpToDate
, t.ScanningEnabled
, t.Expired
, t.ScanTime
, Row_Number() over (partition by DeviceID order by scanTime Desc) RN
FROM dbo.fact_AVSecurity t)
SELECT *
FROM CTE
WHERE RN=1
如果您的表上有一个自动递增列(通常每个表上都应该有一个),请使用该列而不是时间戳,因为SQL Server
DateTime
类型只有一个,不应假定为唯一的时间戳
SELECT X.LastEntryID, DeviceID = Y.ID, ...
FROM
(
SELECT LastEntryID = MAX(ID)--latest entry for the device
FROM dbo.fact_AVSecurity
GROUP BY DeviceID--you don't even need to return DeviceID since ID is auto-increment and thus unique in the table
) AS X
INNER JOIN dbo.fact_AVSecurity AS Y ON
Y.ID = X.LastEntryID
这假定您不使用对数据进行回溯或填充。如果您的表上有一个自动递增列(通常每个表上都应该有一个),请使用该列而不是时间戳,因为SQL Server
DateTime
类型只有一个时间戳,不应假定它是唯一的时间戳
SELECT X.LastEntryID, DeviceID = Y.ID, ...
FROM
(
SELECT LastEntryID = MAX(ID)--latest entry for the device
FROM dbo.fact_AVSecurity
GROUP BY DeviceID--you don't even need to return DeviceID since ID is auto-increment and thus unique in the table
) AS X
INNER JOIN dbo.fact_AVSecurity AS Y ON
Y.ID = X.LastEntryID
这假定您不会使用最后一个选项回溯数据或填充数据,因为我没有看到提到它 您可以将带领带的
与行编号()配合使用
这就是说,xQbert的解决方案(+1)的性能会更高,尤其是对于较大的表
示例
SELECT Top 1 with ties *
FROM dbo.fact_AVSecurity
Order By Row_Number() over (partition by DeviceID order by scanTime Desc)
只有最后一个选择,因为我没有看到提到它
您可以将带领带的与行编号()配合使用
这就是说,xQbert的解决方案(+1)的性能会更高,尤其是对于较大的表
示例
SELECT Top 1 with ties *
FROM dbo.fact_AVSecurity
Order By Row_Number() over (partition by DeviceID order by scanTime Desc)