sql-server - 检索查询中的最新记录

标签 sql-server sql-server-2005 tsql group-by greatest-n-per-group

我有以下表格:

tblPerson:

PersonID | Name
---------------------
   1     | John Smith
   2     | Jane Doe
   3     | David Hoshi

表位置:

LocationID | Timestamp | PersonID | X | Y | Z | More Columns...
---------------------------------------------------------------
    40     | Jan. 1st  |     3    | 0 | 0 | 0 | More Info...
    41     | Jan. 2nd  |     1    | 1 | 1 | 0 | More Info...
    42     | Jan. 2nd  |     3    | 2 | 2 | 2 | More Info...
    43     | Jan. 3rd  |     3    | 4 | 4 | 4 | More Info...
    44     | Jan. 5th  |     2    | 0 | 0 | 0 | More Info...

我可以生成一个 SQL 查询来获取每个人的位置记录,如下所示:

SELECT LocationID, Timestamp, Name, X, Y, Z 
FROM tblLocation 
JOIN tblPerson 
ON tblLocation.PersonID = tblPerson.PersonID;

产生以下内容:

LocationID | Timestamp |    Name     | X | Y | Z |
--------------------------------------------------
    40     | Jan. 1st  | David Hoshi | 0 | 0 | 0 |
    41     | Jan. 2nd  | John Smith  | 1 | 1 | 0 |
    42     | Jan. 2nd  | David Hoshi | 2 | 2 | 2 |
    43     | Jan. 3rd  | David Hoshi | 4 | 4 | 4 |
    44     | Jan. 5th  | Jane Doe    | 0 | 0 | 0 |

我的问题是我们只关心最新的位置记录。因此,我们只对以下行真正感兴趣:LocationID 41、43 和 44。

问题是:我们如何查询这些表以提供每个人的最新数据?需要进行哪些特殊分组才能产生所需的结果?

最佳答案

MySQL 没有排名/分析/窗口功能。

SELECT tl.locationid, tl.timestamp, tp.name, X, Y, Z
  FROM tblPerson tp
  JOIN tblLocation tl ON tl.personid = tp.personid
  JOIN (SELECT t.personid,
               MAX(t.timestamp) AS max_date
          FROM tblLocation t
      GROUP BY t.personid) x ON x.personid = tl.personid
                            AND x.max_date = tl.timestamp

SQL Server 2005+ 和 Oracle 9i+ 支持分析,因此您可以使用:

SELECT x.locationid, x.timestamp, x.name, x.X, x.Y, x.Z
  FROM (SELECT tl.locationid, tl.timestamp, tp.name, X, Y, Z,
               ROW_NUMBER() OVER (PARTITION BY tp.name ORDER BY tl.timestamp DESC) AS rank
          FROM tblPerson tp
          JOIN tblLocation tl ON tl.personid = tp.personid) x
WHERE x.rank = 1

使用变量获得与 MySQL 上的 ROW_NUMBER 功能相同的功能:

SELECT x.locationid, x.timestamp, x.name, x.X, x.Y, x.Z
  FROM (SELECT tl.locationid, tl.timestamp, tp.name, X, Y, Z,
               CASE
                 WHEN @name != t.name THEN
                   @rownum := 1
                 ELSE @rownum := @rownum + 1
               END AS rank,
               @name := tp.name
          FROM tblLocation tl
          JOIN tblPerson tp ON tp.personid = tl.personid
          JOIN (SELECT @rownum := NULL, @name := '') r
      ORDER BY tp.name, tl.timestamp DESC) x
WHERE x.rank = 1

关于sql-server - 检索查询中的最新记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3182436/

相关文章:

sql - JOIN 和 INNER JOIN 之间的区别

sql - 无法升级/导入 dacpac 文件

c# - 将 C# 嵌套对象保存到 SQL Server 的有效方法

sql - 在更新语句上使用输出子句时出现奇怪的错误?

sql-server-2008 - 为什么这段 SQL 代码不会产生错误?

SQL 计算平均值

sql-server - 如何确定插入时哪一列引发算术溢出错误?

sql-server - 存储过程是否能够从操作系统中删除文件?

sql - 包含计数不工作的内部连接的存储过程

sql-server-2005 - Row_Number() 与联合查询