sql - 对表进行分区以获取日期范围

标签 sql sql-server sql-server-2012 window-functions

我有一个用户的历史记录表,我正在尝试查找该用户持有特定用户名的日期范围。该表是一个由触发器填充的审核表,因此每次用户(而不仅仅是用户名)发生更改时,它都会有条目。我可以这样做来获取每行的日期范围:

CREATE TABLE #LoginHistory
(
  LoginHistoryID INT IDENTITY(1,1),
  LoginID INT,
  Username VARCHAR(32),
  StartDate DATETIME
)

INSERT INTO #LoginHistory (LoginID, Username, StartDate) VALUES
(1, 't', '2016-01-01'),
(1, 't', '2016-01-02'),
(1, 't', '2016-01-04'),
(1, 'test', '2016-01-05'),
(2, 't', '2016-01-08'),
(2, 'tom', '2016-01-09'),
(1, 'test', '2016-01-15'),
(1, 't', '2016-02-01')

SELECT
    LoginID,
    Username,
    StartDate,
    EndDate = LEAD(StartDate) OVER (PARTITION BY LoginID ORDER BY StartDate ASC)
FROM #LoginHistory
WHERE LoginID = 1
ORDER BY StartDate ASC

DROP TABLE #LoginHistory

输出:

LoginID  Username  StartDate                EndDate
1        t         2016-01-01 00:00:00.000  2016-01-02 00:00:00.000
1        t         2016-01-02 00:00:00.000  2016-01-04 00:00:00.000
1        t         2016-01-04 00:00:00.000  2016-01-05 00:00:00.000
1        test      2016-01-05 00:00:00.000  2016-01-15 00:00:00.000
1        test      2016-01-15 00:00:00.000  2016-02-01 00:00:00.000
1        t         2016-02-01 00:00:00.000  NULL

但是,我真正想做的是折叠每个用户名持续时间,以便用户持有用户名的每个日期范围都有一行。基本上,我正在寻找这个输出:

LoginID  Username  StartDate                EndDate
1        t         2016-01-01 00:00:00.000  2016-01-05 00:00:00.000
1        test      2016-01-05 00:00:00.000  2016-02-01 00:00:00.000
1        t         2016-02-01 00:00:00.000  NULL

我该如何正确折叠这些行?

最佳答案

您可以使用以下查询:

SELECT LoginID,
       Username,
       MIN(StartDate) AS StartDate,
       MAX(EndDate) AS EndDate
FROM (
  SELECT
      LoginID,
      Username,
      StartDate,
      EndDate = LEAD(StartDate) OVER (PARTITION BY LoginID 
                                      ORDER BY StartDate ASC),
      ROW_NUMBER() OVER (ORDER BY StartDate) -
      ROW_NUMBER() OVER (PARTITION BY LoginID, Username 
                         ORDER BY StartDate) AS grp
  FROM #LoginHistory
  WHERE LoginID = 1) AS t
GROUP BY LoginID, Username, grp
ORDER BY StartDate ASC

grp 可帮助您识别具有相同 LoginID、Username 值的连续行。

关于sql - 对表进行分区以获取日期范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35556293/

相关文章:

sql-server - DT_Decimal 数据类型 截除小数

SQL 基本并发

mysql - MYSQL中如何对列进行排序

SQL:带有 ORDER BY 子句的 SELECT TOP 不返回正确的结果

tsql - 选择所有未设置标志的记录

sql-server - 列出 sql server 2012 中的架构名称和所有者

sql - 查找前 n 个平均值

sql - 将解释计划中的日期显示为文字

SQL表选择

sql - 如何在 SQL Server 中获取查询执行计划?