我有一些像这样的客户的历史表等:
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
答案 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