sql - 为表格中的每一行选择上一个日期

标签 sql sql-server select

我有一张表可以跟踪在任意时间点发生的机器维护。这是一个简化的表结构:

Maintenance Table
----------------------------------------
ID            - integer
DateCompleted - date
MachineName   - varchar

下面是一些示例表数据:

ID   DateCompleted MachineName
----------------------------------------
1     1/6/2011     'Machine 1'
2     1/13/2011    'Machine 2'
3     1/14/2011    'Machine 1'
4     2/2/2011     'Machine 3'
5     2/26/2011    'Machine 1'
6     3/9/2011     'Machine 2'
7     4/20/2011    'Machine 3'

我想做的是创建一个查询,该查询将为每个任务返回上一个维护任务的日期。所以结果集会是这样的:

ID   MachineName  CurDate     PrevDate
----------------------------------------
1    'Machine 1'    1/6/2011    NULL
2    'Machine 2'    1/13/2011   NULL
3    'Machine 1'    1/14/2011   1/6/2011
4    'Machine 3'    2/2/2011    NULL
5    'Machine 1'    2/26/2011   1/14/2011
6    'Machine 2'    3/9/2011    1/13/2011
7    'Machine 3'    4/20/2011   2/2/2011

编写此类查询的最佳方式是什么?到目前为止,我唯一的想法是这样的:

SELECT ID, MachineName, DateCompleted AS CurDate,
  (
    SELECT TOP 1 DateCompleted FROM Maintenance m2
    WHERE m1.MachineName = m2.MachineName
      AND m1.DateCompleted > m2.DateCompleted
    ORDER BY DateCompleted DESC
  ) AS PrevDate

FROM Maintenance m1

ORDER BY ID

任何想法、建议或更正都将非常受欢迎。

最佳答案

正如您所说“但我欢迎任何解决方案”。

这是一个使用 ANSI SQL 的解决方案:

SELECT ID, 
       DateCompleted, 
       MachineName, 
       lag(DateCompleted) over (partition by MachineName order by DateCompleted) as PrevDate 
FROM Maintenance 
ORDER BY id;

适用于 PostgreSQL、Oracle、DB2 和 Teradata。

SQL Server 尚不支持 lag() 函数,但即将推出的“Denali”版本 (2012) 将会支持。

关于sql - 为表格中的每一行选择上一个日期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8856058/

相关文章:

MySQL 从 SELECT 中更新字段

mysql - 如何忽略where子句中的条件

sql - 如何在不影响已经存在的值的情况下更改列的属性?

mysql - 如何为 InnoDB 引擎数据库重新播种 "Auto increment"列?

mySQL按值求和

sql-server - 暂时禁用所有外键约束

sql-server - SQL Server 全文搜索 : different results of parsing forms of words

sql-server - 对输出子句 sql 进行过滤

php - 插入新行,更新旧行 : how?

mysql - 优化缓慢的 mysql 查询