SQL查询 - 获取具有时间段的历史数据

时间:2015-01-14 14:20:22

标签: sql sql-server group-by history

我有一些像这样的客户的历史表等:

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
...

我需要编写一个返回数据集的查询

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

这意味着我想按时间顺序获取克林特和一个城市的日期。我不关心地位。 我使用了这样的查询:

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

1 个答案:

答案 0 :(得分:1)

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表添加到上一个和下一个城市,以便用于检测主查询中的更改

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

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

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