Sql query - 获取带时间段的历史数据

Sql query - getting history data with time period

我有一些这样的客户的历史记录 table,等等:

ID    CLIENT_ID    CITY     STATUS_ID    VALID_FROM    VALID_TO
---------------------------------------------------------------
1     150          NEW YORK 1            2000-01-01    2001-01-01
2     150          NEW YORK 2            2001-01-01    2002-01-01
3     150          NEW YORK 1            2002-01-01    2003-01-01    
4     150          LONDON   1            2003-01-01    2004-01-01
5     150          LONDON   2            2004-01-01    2005-01-01
6     150          NEW YORK 2            2005-01-01    2006-01-01
...

我需要编写一个查询,它将return这样的数据集

CITY         VALID_FROM    VALID_TO
--------------------------------------
NEW YORK     2000-01-01    2003-01-01
LONDON       2003-01-01    2005-01-01
NEW YORK     2005-01-01    2006-01-01

这意味着我想按时间顺序获取 Clint 和城市的日期时间段。我不在乎状态。 我使用这样的查询:

Select CLIENT_ID, CITY, MIN(VALID_FROM), MAX(VALID_TO)
from HISTORY_TABLE
group by CLIENT_ID, CITY
order by 3 asc

如果 NEW YORK 不再出现在最后一行中就好了。

有什么建议吗? 我正在使用 MSSQL 2012

WITH t AS
(
SELECT *, ISNULL(Lag(city,1) OVER(ORDER BY client_id,id), 'first') prevcity, 
ISNULL(Lead(city,1) OVER(ORDER BY client_id,id), 'last') nextcity FROM HISTORY_TABLE
)

SELECT t1.client_id, t1.city, t1.valid_from, ISNULL(t2.valid_to,t1.valid_to) FROM t t1
LEFT JOIN t t2 
ON t1.city=t2.city AND t1.city=t2.prevcity AND t1.client_id=t2.client_id AND t2.city<>t2.nextcity AND t2.id>=t1.id
WHERE t1.city<>t1.prevcity
ORDER BY client_id, id

这个查询试图做的是

  • 添加到CTE table t 上一个和下一个城市,以便用于检测主查询中的变化

  • 在主查询中,where 子句确定客户端在新城市开始的行

  • CTE t 自行加入以查找此客户的下一个城市更改

  • 客户端的最后一条记录将找不到下一个更改,但被 valid_to

  • 的 isnull 覆盖