SQL Server查询。按最新日期加入

时间:2011-03-22 14:28:57

标签: sql sql-server

我有3张桌子:

UnitInfo(UnitID, ...), 
UnitList(UnitID, ...) 
UnitMonitoring(RecordID,UnitID, EventDate, ...)

UnitListUnitInfo的子集(就数据和列而言)。 UnitMonitoring会及时收到与UnitList相关的记录(UnitIDUnitMonitoring我们将有许多记录)EventDate。 (UnitInfo已扩展信息)。

我无法确定如何构建查询,以便对UnitID中的每个UnitList我都会得到UnitMonitoring记录,以便EventDate是最新的记录。

到目前为止我已经

SELECT a.UnitID, a.Name, b.EventDate 
FROM UnitInfo a INNER JOIN UnitMonitoring b 
WHERE a.UnitID IN (SELECT UnitID FROM UnitList) 

产生UnitMonitoring

的所有记录

4 个答案:

答案 0 :(得分:4)

SELECT  ul.unitId, um.*
FROM    UnitList ul
OUTER APPLY
        (
        SELECT  TOP 1 *
        FROM    UnitMonitoring umi
        WHERE   umi.UnitID = ul.unitID
        ORDER BY
                EventDate DESC
        )

这将正确处理重复项并返回所有单位(UnitMonitoring中没有记录的单位将在相应字段中显示NULL个值)

答案 1 :(得分:2)

尝试:

Select M.* 
From UnitList L 
  Join UnitMonitoring M
    On M.UnitId = L.UnitId
Where M.EventDate = 
   (Select Max(EventDate) From UnitMonitoring 
    Where UnitId = M.UnitId)

如果有多个记录具有相同的UnitId和EventDate,那么您仍然可以使用此技术,但是您需要对唯一字段进行过滤,例如,在这种情况下,UnitMonitoring中的PK字段名为PkId

Select M.* 
From UnitList L 
  Join UnitMonitoring M
    On M.UnitId = L.UnitId
Where M.PkId = 
   (Select Max(PkId) From UnitMonitoring iM
    Where UnitId = M.UnitId
        And EventDate = 
             (Select Max(EventDate) From UnitMonitoring 
              Where UnitId = M.UnitId))

答案 2 :(得分:2)

我选择使用Common Table Expression(CTE)来应用排名功能(ROW_NUMBER):

;WITH NumberedMonitoring as (
     SELECT RecordID,UnitID, EventDate, ...
          ROW_NUMBER() over (PARTITION BY UnitID ORDER BY EventDate desc) rn
     FROM UnitMonitoring
)
SELECT * FROM
    UnitList ul
        inner join
    NumberedMonitoring nm
        on
            ul.UnitID = nm.UnitID and nm.rn = 1

但是有许多不同的解决方案(上面也可以使用子选择来完成)。

公用表格表达式(引自上面的链接):

  

公用表表达式(CTE)可以被认为是临时结果集

也就是说,它允许您先写一些查询。在这种情况下,我使用它是因为我想对行进行编号(使用ROW_NUMBER函数)。我告诉它重新开始每个UnitID(PARTITION BY UnitID)的编号,并且在每个单元ID中,我希望根据EventDate降序编号的行(ORDER BY EventDate desc)。这意味着接收第1行(在每个UnitID分区内)的行是最新的行。

在下面的选择中,我能够将我的CTE(NumberedMonitoring)视为任何其他表格。所以我只是将它加入UnitList表,并确保作为连接条件的一部分,我只选择第1行(rn = 1

答案 3 :(得分:1)

SELECT a.UnitID, a.Name, MAX(b.EventDate) 
FROM UnitInfo a 
INNER JOIN UnitMonitoring b 
WHERE a.UnitID IN (SELECT UnitID FROM UnitList)
GROUP BY a.UnitID, a.Name