选择很多TOP 1

时间:2011-09-13 17:46:11

标签: sql sql-server-2008 select

在SQL Server 2008数据库中,我有以下表格:

CREATE TABLE t_DeviceType
(
    ID INTEGER PRIMARY KEY IDENTITY, 
    Device VARCHAR(32) NOT NULL 
)

CREATE TABLE t_Device
(
    ID INTEGER PRIMARY KEY IDENTITY, 
    DeviceTypeID INTEGER NOT NULL,
    IPAddress INTEGER NOT NULL,
    RegTime DATETIME NOT NULL,
    IsActive BIT NOT NULL
)

现在我想要一个查询,它将为所有设备类型提取最后一个已注册但仍处于活动状态的设备(如果有)。

对于单个给定设备,这很容易:

SELECT TOP 1 *
FROM t_Device
WHERE IsActive = 1
  AND DeviceTypeID = 42 -- For example
ORDER BY RegTime DESC

但是,对于DeviceTypeID所有可能的价值,我需要这样做。

我以为我可以使用JOIN语句来完成它,但是我无法有效地限制JOIN提取的记录数。

我尝试了以下内容:

SELECT t_DeviceType.ID AS TypeID, 
       t_DeviceType.Device, 
       Device.ID AS DeviceID, 
       Device.IPAddress AS IPAddress
FROM t_DeviceType
JOIN ( 
    SELECT TOP 1 t_Device.ID, DeviceTypeID, IPAddress 
    FROM t_Device
    JOIN t_DeviceType ON DeviceTypeID = t_DeviceType.ID
    WHERE IsActive = 1
    ORDER BY RegTime DESC
) AS Device ON Device.ConsoleTypeID = t_DeviceType.ID

但这只返回了任何类型的最后一个注册的偏差。

有人有建议吗?

谢谢,

2 个答案:

答案 0 :(得分:5)

您希望获取设备列表及其关联的最大RegTime。

SELECT DeviceTypeID, max(RegTime) as LatestRegTime
FROM t_Device
WHERE IsActive = 1
GROUP BY DeviceTypeID

现在你可以将它作为派生表使用并加入它(而不是你试过的select top 1):

SELECT t_DeviceType.ID AS TypeID, 
       t_DeviceType.Device, 
       Device.ID AS DeviceID, 
       Device.IPAddress AS IPAddress
FROM t_DeviceType
JOIN ( 
    SELECT t_Device.ID, 
           IPAddress, 
           DeviceTypeID, 
           max(RegTime) as LatestRegTime
    FROM t_Device
    WHERE IsActive = 1
    GROUP BY t_Device.ID, IPAddress, DeviceTypeID
) AS Device ON Device.DeviceTypeID = t_DeviceType.ID

答案 1 :(得分:0)

在SQL Server 2008中,您还可以使用ranking来实现您的目标:

SELECT
  t.ID AS TypeID,
  t.Device,
  d.ID AS DeviceID,
  d.IPAddress
FROM (
 SELECT
   *,
   rnk = RANK() OVER (PARTITION BY DeviceTypeID ORDER BY RegTime DESC)
 FROM t_Device
) d
  INNER JOIN t_DeviceType t ON d.DeviceTypeID = t.ID
WHERE d.rnk = 1