从具有多个表的多个列中选择不同的值

时间:2017-04-21 04:16:16

标签: sql-server

查看以下编辑

我正在尝试在SQL Server 2012中构建一个显示以下内容的列表:

Serial    FW_Ver  DeviceName  UserName  LastUpload           LastRecord
12345678  998     Test1       User1     2016-02-22 17:31:28  2016-02-19 11:14:15
45678912  998     Test2       User5     2016-03-14 16:24:17  2016-03-14 12:24:57
78978979  600     Test3       User12    2016-01-31 09:12:48  2016-01-30 23:49:12
45554468  NULL    Test4       NULL      NULL                 NULL

这是从同一数据库中的3个不同表构建的。设备表中的序列号都是唯一的,没有重复项,所以我希望看到所有序列号返回的结果,即使它们还没有上传任何文件。我当前的查询给了我想要的结果,但是有一些不需要的添加,如下所示(前3行):

Serial    FW_Ver  DeviceName  UserName  LastUpload           LastRecord
12345678  772     Test1       User1     2016-02-22 17:30:18  2014-01-01 16:19:06
12348678  891     Test1       User1     2016-02-22 17:30:31  2015-02-16 15:41:56
12345678  998     Test1       User1     2016-02-22 17:31:28  2016-02-19 11:14:15
45678912  998     Test2       User5     2016-03-14 16:24:17  2016-03-14 12:24:57
78978979  600     Test3       User12    2016-01-31 09:12:48  2016-01-30 23:49:12
45554468  NULL    Test4       NULL      NULL                 NULL

正如您所看到的,我正在为其使用的每个固件版本获取特定设备的最新日期时间。我不想要这个,我只想要从最新文件列出的最新日期时间,无论固件版本如何。

到目前为止,这是我的查询:

SELECT d.Serial,
de.Firmware AS FW_Ver,
d.DeviceName,
MAX(de.CreatedOn) AS LastUploadedDate,
MAX(de.EventTimeStamp) AS LastRecordingDate

FROM AuroraCore.dbo.DeviceEvent AS de
RIGHT JOIN AuroraCore.dbo.Device AS d ON d.Id = de.DeviceId

GROUP BY d.Serial, de.firmware, d.DeviceName

我尝试使用MAX(de.Firmware) OVER (PARTITION BY d.serial) AS FW_Ver,但返回相同数量的结果,然后固件版本仅显示为该给定设备的最高编号(998 x3而不是772,891和998,如上表中的前三行)。

如何仅从给定设备的最新文件中提取日期时间并返回相应版本的固件?我希望上传日期的优先级跟随记录日期。谢谢!

编辑1:我可以使用此功能删除额外的不需要的信息:

SELECT d.Serial, 
t.Firmware AS FW_Ver, 
d.DeviceName, 
MAX(t.CreatedOn) AS LastUpload, 
MAX(t.EventTimeStamp) AS LastRecord

FROM (
    SELECT de.DeviceId, 
    de.Firmware, 
    de.CreatedOn, 
    de.EventTimeStamp, 
    ROW_NUMBER() OVER (PARTITION BY DeviceId ORDER BY Firmware DESC) AS RN 
    FROM AuroraCore.dbo.DeviceEvent AS de
) AS t

RIGHT JOIN AuroraCore.dbo.Device AS d ON d.Id = t.DeviceId

WHERE RN = 1

GROUP BY d.serial, t.Firmware, d.DeviceName

现在的问题是WHERE RN = 1导致没有NULL值返回,而我需要显示这些值。删除WHERE会获得与以前完全相同的结果列表。我在哪里可以移动/调整WHERE RN = 1子句,以便还返回NULL个值?

1 个答案:

答案 0 :(得分:1)

我通过以下查询得到了它:

SELECT d.Serial, 
t.Firmware AS FW_Ver, 
d.DeviceName, 
MAX(t.CreatedOn) AS Upload, 
MAX(t.EventTimeStamp) AS Record

FROM (
    SELECT de.DeviceId, 
    de.Firmware, 
    de.CreatedOn, 
    de.EventTimeStamp, 
    ROW_NUMBER() OVER (PARTITION BY DeviceId ORDER BY Firmware DESC) AS RN 
    FROM AuroraCore.dbo.DeviceEvent AS de
) AS t

RIGHT JOIN AuroraCore.dbo.Device AS d ON d.Id = t.DeviceId

WHERE RN = 1 OR t.CreatedOn is NULL

GROUP BY d.serial, t.Firmware, d.DeviceName

我添加到我之前编辑的所有内容都是OR t.CreatedOn is NULL,其中包含我想要的NULL值。将ROW_NUMBER() OVER PARTITIONWHERE RN = 1结合使用可以摆脱显示的较旧固件版本,因为子查询只会返回最高版本的固件(由PARTITION BY DeviceId ORDER BY Firmware DESC指示)一个给定的设备,随后只有上传和记录日期的最新日期时间。