2011-11-14 55 views
0

我有DeviceMaster和DeviceStatus的表。 其中DeviceMaster是设备的主设备,而DeviceStatus是设备的状态。现在我想要使用DeviceMasterId获取每个设备的最新DeviceStatus记录,并且根据最后一个记录(降序)。创建SQL查询

例如。

DeviceName  RecordCreatedDate  Status 
ElectronicRod  14/11/2011 12:00:00  On 
ElectronicRod  14/11/2011 11:30:00  Off 

尽管在DeviceStatus中有多个记录。

这里是表结构

DeviceMaster

[Id] [int], 
[ROId] [int] , 
[ClientId] [int] , 
[DeviceTypeId] [int] , 
[Label] [varchar](50) , 
[ClientCommChannelId] [int] , 
[ServerCommChannelId] [bigint] , 
[DeviceName] [varchar](50) , 
[Address] [varchar](50) , 
[Attribute1] [varchar](50) , 
[Attribute2] [varchar](50) , 
[Attribute3] [varchar](50) , 
[IsDeleted] [bit] , 
[RecordCreatedDate] [datetime] , 
[RecordUpdatedDate] [datetime] , 
[RecordCreatedBy] [int] , 
[RecordUpdatedBy] [int] , 
[IsTransfered] [bit] 

DeviceStatus

[Id] [bigint], 
[ROId] [int], 
[ClientId] [int], 
[ServerDeviceId] [bigint] , --It is the foreign key reference of Device Id 
[ClientDeviceId] [int] , 
[Status] [bit] , 
[TimeStamp] [datetime] , 
[Attribute1] [varchar](50) , 
[Attribute2] [varchar](50) , 
[Attribute3] [varchar](50) , 
[RecordCreatedDate] [datetime] , 
[RecordUpdatedDate] [datetime] , 
[RecordCreatedBy] [int] , 
[RecordUpdatedBy] [int] , 
[IsTransfered] [bit] 

DeviceStatus具有多行条目单device.I需要最新DeviceStatus每个和每个设备。

预先感谢您

+1

你可以发表表格结构吗?你还有什么尝试过自己?你有任何代码等? – Purplegoldfish

+0

@Purplegoldfish sure –

+0

您能否澄清DeviceStatus是否是一个审计表,显示状态更改的历史记录,而不是当前状态。 –

回答

1

可以使用CTE(公共表表达式)与ROW_NUMBER功能:可通过DeviceMasterId

;WITH LastPerDevice AS 
(
    SELECT 
     dm.DeviceName, ds.RecordCreatedDate, ds.Status, 
     ROW_NUMBER() OVER(PARTITION BY dm.DeviceMasterId 
         ORDER BY ds.RecordCreatedDate DESC) AS 'RowNum' 
    FROM dbo.DeviceMaster dm 
    INNER JOIN dbo.DeviceStatus ds ON ds.DeviceMasterId = dm.DeviceMasterId 
) 
SELECT 
    DeviceName, RecordCreatedDate, Status 
FROM LastPerDevice 
WHERE RowNum = 1 

这CTE“分区”您的数据,并为每个分区, ROW_NUMBER函数提供连续数字,从1开始,并按RecordCreatedDate DESC排序 - 因此最近的一行获得RowNum = 1(对于每个DeviceMasterId),这是我在SELECT语句后从CTE中选择的顺序号。

+0

非常感谢:)完美的作品 –

+0

不错。如果你的表格非常大,我会建议对此进行性能测试。 (使用SET STATISTICS IO ON运行)。与此处的其他答案进行比较,并查看哪个给出了最低的IO /努力量。 –

0
select dm.DeviceName, ds1.LatestDate, ds2.Status 
from DeviceMaster dm, 
    (select ServerDeviceId, max(RecordCreatedDate) as LatestDate 
    from DeviceStatus 
    group by ServerDeviceId) ds1, 
    DeviceStatus ds2 
where dm.Id = ds1.ServerDeviceId 
    and dm.Id = ds2.ServerDeviceId 
    and ds1.LatestDate = ds2.RecordCreatedDate 
order by ds1.LatestDate desc 
+0

好的,我完成了锤击...请尝试:) – kol

0

我不是很积极你在找什么,但是下面在where子句中使用子查询来过滤最后的日期。也许如果这不是你正在寻找的东西,它可能会帮助你找到它。让我知道你是否需要我澄清任何事情。

select DeviceName, RecordCreateDated, Status 
    from DeviceMaster dm join 
      DeviceStatus ds on dm.Id = ds.ServiceDeviceId 
    where DeviceName = 'ElectronicRod' and 
      RecordCreateDate = 
       (select max(RecordCreatedDate) 
       from DeviceMaster dm1 join 
         DeviceStatus ds1 on dm1.Id = ds1.ServiceDeviceId 
       where dm1.DeviceName = dm.DeviceName) 
0

使用MAX(),GROUP BY方法

你的代码看起来probbly有点像这样:

SELECT max("DeviceStatus") as "devicestatus" , "Id" FROM "DeviceMaster" 
group by "Id"; 

编辑:

SELECT max("RecordCreatedDate") as "Date" , "DeviceName" FROM "DeviceMaster" 
group by "Name"; 
+0

如果它是一个BIT,最大值将始终为1(除非状态始终为0)。你不想要MAX,你想要最新! –

0

你想每个设备状态表中最新记录的状态。 这意味着您需要实际执行两次到状态表的连接 - 一个表获取最新的行(由设备分组),然后再次获取最新状态的状态。像这样:

我看到你有大人 - 这表明我的状态表很大。这表明它经常更新。确保状态表在ServerDeviceId上编入索引。

select DeviceName ,ds.RecordCreatedDate,ds.Status 
from 
DeviceMaster dm inner join 
(select ServerDeviceId,MAX(Id) DeviceStatusId from DeviceStatus 
group by ServerDeviceId) laststatus 
    on laststatus.ServerDeviceId= dm.Id inner join 
DeviceStatus ds 
    on ds.Id = laststatus.DeviceStatusId 
+0

这和我的几乎一样:)你通过使用max(Id)和加入Id上的状态表做得更好 - 我在ServerDeviceId和创建日期加入了它们,这有点愚蠢。根据ds.RecordCreatedDate添加降序,并且此解决方案变得完美:) – kol