如何只从左表获得一个记录,而从右表获得每个记录

时间:2019-01-14 07:39:41

标签: sql-server join subquery query-performance sqlperformance

我有两个表,一个表用于某种设备,另一个表用于其位置(使用此表记录位置历史记录)。表的架构为:

  1. tbl_Devices:

    • DeviceSrNumber(bigint,不为null,pk)
    • 其他一些列
  2. tbl_DeviceLocation

    • SrNumber(bigint,不为null,pk,身份)
    • DeviceSrNumber(bigint,不为null)
    • 位置(varchar(300),不为null)
    • AddDateTime(DateTime,不为null)

我需要的是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

但是我需要以一种更简洁的方式进行连接,因为据我所知,子查询效率不高,因此不建议在大型数据库中使用。

注意:这只是大型项目的一小部分,它将处理数百万条记录。

3 个答案:

答案 0 :(得分:1)

您可以从这里开始:

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

答案 1 :(得分:1)

您的查询将以这种方式更加高效:

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;

答案 2 :(得分:-1)

尝试此操作,它将使用最新的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

更新

我尝试过此操作,它根据最新记录选择了不同的记录。希望能解决

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