如何仅从左侧 table 获取一条记录,而从右侧 table 获取每条记录
How to get only one record from left table against each record from right table
我有两个 table,一个用于某种设备,另一个用于它们的位置(使用这个 table 来记录位置历史记录)。表的架构是:
tbl_Devices:
- DeviceSrNumber(bigint,不为空,pk)
- 其他一些栏目
tbl_DeviceLocation
- SrNumber (bigint, not null, pk, identity)
- DeviceSrNumber(bigint,不为空)
- 位置(varchar(300),不为空)
- AddDateTime(日期时间,不为空)
我需要的是DeviceSrNumber
,最后一个Location
,最后一个位置设置AddDateTime
我现在在做什么:
SELECT
DeviceSrNumber,
(
SELECT TOP (1) Location
FROM tbl_DeviceLocation
WHERE (DeviceSrNumber = d.DeviceSrNumber)
ORDER BY AddDateTime DESC
) AS 'Location',
(
SELECT TOP (1) AddDateTime
FROM tbl_DeviceLocation
WHERE (DeviceSrNumber = d.DeviceSrNumber)
ORDER BY AddDateTime DESC
) AS 'AddDateTime '
FROM
tbl_Devices AS d
但我需要以更简洁的方式使用连接来完成,因为据我所知,子查询效率不高,不建议在大型数据库中使用。
注意:它是一个大型项目的一小部分,它将处理数百万条记录。
你可以从这个开始:
SELECT *
FROM (
SELECT
d.DeviceSrNumber
, dl.Location LastLocation
, dl.AddDateTime LastLocationSetDateTime
, ROW_NUMBER() OVER(PARTITION BY d.DeviceSrNumber ORDER BY AddDateTime DESC) RN
FROM
tbl_Devices d
JOIN tbl_DeviceLocation dl ON dl.DeviceSrNumber = d.DeviceSrNumber
) D
WHERE
RN = 1
更新
SELECT
d.DeviceSrNumber
, MAX(dl.Location) LastLocation
, MAX(dl.AddDateTime) LastLocationSetDateTime
FROM
tbl_Devices d
JOIN tbl_DeviceLocation dl ON dl.DeviceSrNumber = d.DeviceSrNumber
GROUP BY d.DeviceSrNumber
ORDER BY AddDateTime DESC
这样您的查询会更有效率:
SELECT D.DeviceSrNumber,
L.Location,
L.AddDateTime
FROM tbl_Devices D
OUTER APPLY
(SELECT TOP (1) DL.Location, DL.AddDateTime
FROM tbl_DeviceLocation DL
WHERE D.DeviceSrNumber = DL.DeviceSrNumber
ORDER BY DL.AddDateTime DESC
) L;
试试这个,它会 select 使用最新的 AddDateTime
一个数据
SELECT top(1) D.DeviceSrNumber, L.Location,L.AddDateTime
FROM tbl_Devices AS D
JOIN tbl_DeviceLoation AS L ON D.DeviceSrNumber = L.DeviceSrNumber
WHERE D.DeviceSrNumber = L.DeviceSrNumber order by L.AddDateTime desc
更新
我试过了,它根据最新记录 select 不同的记录。希望这能解决问题
WITH CTE AS
(
SELECT D.DeviceSrNumber, L.Location,L.AddDateTime , RN= ROW_NUMBER() OVER (PARTITION BY D.DeviceSrNumber ORDER BY D.DeviceSrNumber)
FROM tbl_Devices AS D LEFT JOIN tbl_DeviceLoation AS L ON D.DeviceSrNumber = L.DeviceSrNumber
WHERE D.DeviceSrNumber = L.DeviceSrNumber group by D.DeviceSrNumber, L.Location,L.AddDateTime )
SELECT * FROM CTE where RN=1 order by CTE.AddDateTime desc
我有两个 table,一个用于某种设备,另一个用于它们的位置(使用这个 table 来记录位置历史记录)。表的架构是:
tbl_Devices:
- DeviceSrNumber(bigint,不为空,pk)
- 其他一些栏目
tbl_DeviceLocation
- SrNumber (bigint, not null, pk, identity)
- DeviceSrNumber(bigint,不为空)
- 位置(varchar(300),不为空)
- AddDateTime(日期时间,不为空)
我需要的是DeviceSrNumber
,最后一个Location
,最后一个位置设置AddDateTime
我现在在做什么:
SELECT
DeviceSrNumber,
(
SELECT TOP (1) Location
FROM tbl_DeviceLocation
WHERE (DeviceSrNumber = d.DeviceSrNumber)
ORDER BY AddDateTime DESC
) AS 'Location',
(
SELECT TOP (1) AddDateTime
FROM tbl_DeviceLocation
WHERE (DeviceSrNumber = d.DeviceSrNumber)
ORDER BY AddDateTime DESC
) AS 'AddDateTime '
FROM
tbl_Devices AS d
但我需要以更简洁的方式使用连接来完成,因为据我所知,子查询效率不高,不建议在大型数据库中使用。
注意:它是一个大型项目的一小部分,它将处理数百万条记录。
你可以从这个开始:
SELECT *
FROM (
SELECT
d.DeviceSrNumber
, dl.Location LastLocation
, dl.AddDateTime LastLocationSetDateTime
, ROW_NUMBER() OVER(PARTITION BY d.DeviceSrNumber ORDER BY AddDateTime DESC) RN
FROM
tbl_Devices d
JOIN tbl_DeviceLocation dl ON dl.DeviceSrNumber = d.DeviceSrNumber
) D
WHERE
RN = 1
更新
SELECT
d.DeviceSrNumber
, MAX(dl.Location) LastLocation
, MAX(dl.AddDateTime) LastLocationSetDateTime
FROM
tbl_Devices d
JOIN tbl_DeviceLocation dl ON dl.DeviceSrNumber = d.DeviceSrNumber
GROUP BY d.DeviceSrNumber
ORDER BY AddDateTime DESC
这样您的查询会更有效率:
SELECT D.DeviceSrNumber,
L.Location,
L.AddDateTime
FROM tbl_Devices D
OUTER APPLY
(SELECT TOP (1) DL.Location, DL.AddDateTime
FROM tbl_DeviceLocation DL
WHERE D.DeviceSrNumber = DL.DeviceSrNumber
ORDER BY DL.AddDateTime DESC
) L;
试试这个,它会 select 使用最新的 AddDateTime
一个数据SELECT top(1) D.DeviceSrNumber, L.Location,L.AddDateTime
FROM tbl_Devices AS D
JOIN tbl_DeviceLoation AS L ON D.DeviceSrNumber = L.DeviceSrNumber
WHERE D.DeviceSrNumber = L.DeviceSrNumber order by L.AddDateTime desc
更新
我试过了,它根据最新记录 select 不同的记录。希望这能解决问题
WITH CTE AS
(
SELECT D.DeviceSrNumber, L.Location,L.AddDateTime , RN= ROW_NUMBER() OVER (PARTITION BY D.DeviceSrNumber ORDER BY D.DeviceSrNumber)
FROM tbl_Devices AS D LEFT JOIN tbl_DeviceLoation AS L ON D.DeviceSrNumber = L.DeviceSrNumber
WHERE D.DeviceSrNumber = L.DeviceSrNumber group by D.DeviceSrNumber, L.Location,L.AddDateTime )
SELECT * FROM CTE where RN=1 order by CTE.AddDateTime desc