组合并显示分布在一行中多行的字段

时间:2017-07-18 05:32:18

标签: sql sql-server sql-server-2012

对于某人的地址变更记录表T

+----------+----------+----------+--------+-----------------+-------------------+-----------------+
| DetailID | PersonID | ChangeID | TypeID | ChangeDateTime  |     OldDetail     |    NewDetail    |
+----------+----------+----------+--------+-----------------+-------------------+-----------------+
|        1 |       10 |        1 |      7 | 7/11/2017 15:48 | 510 S Spring St   | 115 E 3rd St    |
|        2 |       10 |        2 |      7 | 7/6/2017 13:27  | 3351 Westwood     | 510 S Spring St |
|        3 |       10 |        2 |      9 | 7/6/2017 13:27  | San Diego         | Los Angeles     |
|        4 |       10 |        3 |      7 | 6/29/2017 10:38 | 661 Shatto Pl     | 3351 Westwood   |
|        5 |       10 |        3 |      9 | 6/29/2017 10:38 | Los Angeles       | San Diego       |
|        6 |       10 |        4 |      7 | 3/3/2017 13:14  | 3835 W 8th St     | 661 Shatto Pl   |
|        7 |       10 |        5 |      7 | 11/22/2016 9:23 | 123 Park          | 3835 W 8th St   |
|        8 |       10 |        5 |      9 | 11/22/2016 9:23 | San Francisco     | Los Angeles     |
|        9 |       10 |        6 |      7 | 8/3/2016 14:50  | 6650 Franklin Ave | 123 Park        |
|       10 |       10 |        6 |      9 | 8/3/2016 14:50  | Los Angeles       | San Francisco   |
+----------+----------+----------+--------+-----------------+-------------------+-----------------+

DetailID是PK。 ChangeID每次代表地址或地址+城市变化。 TypeID表示更改类型:7表示地址更改,9表示城市更改。

我正在尝试组合这些记录,以便每次更改都有1行描述地址和城市变化,而不是分布在多行上。如果此人在同一个城市内移动,我希望从上次记录/更新城市时复制该城市。

期望输出:

+----------+------------------------+--------------------------------+------------------------------+
| ChangeID |       ChangeDateTime   |           OldDetail            |          NewDetail           |
+----------+------------------------+--------------------------------+------------------------------+
| 1        | 7/11/2017 15:48        | 510 S Spring St, Los Angeles   | 115 E 3rd St, Los Angeles    |
| 2        | 7/6/2017 13:27         | 3351 Westwood, San Diego       | 510 S Spring St, Los Angeles |
| 3        | 6/29/2017 10:38        | 661 Shatto Pl, Los Angeles     | 3351 Westwood, San Diego     |
| 4        | 3/3/2017 13:14         | 3835 W 8th St, Los Angeles     | 661 Shatto Pl, Los Angeles   |
| 5        | 11/22/2016 9:23        | 123 Park, San Francisco        | 3835 W 8th St, Los Angeles   |
| 6        | 8/3/2016 14:50         | 6650 Franklin Ave, Los Angeles | 123 Park, San Francisco      |
+----------+------------------------+--------------------------------+------------------------------+

从下到上阅读,因为排序是通过降序日期时间,最新地址是最顶层。因此,这个人首先生活在洛杉矶富兰克林大街6650号,然后经过一系列的改变最终落到洛杉矶第三街115号。

我无法尝试代码给我这个

1 个答案:

答案 0 :(得分:1)

最简单的解决方案(只要SQL Server不支持IGNORE NULLS的{​​{1}}选项)基于递归。由于这不允许聚合等,您必须首先实现一个透视结果。 这可以使用条件聚合

来完成
LAST_VALUE

然后它只是逐行遍历数据(假设每个人的地址变化很少,这应该是合理的快速):

select PersonID, ChangeId, ChangeDateTime, 
   max(case when TypeID = 7 then OldDetail end) as OldAddress,
   max(case when TypeID = 9 then OldDetail end) as OldCity,
   max(case when TypeID = 7 then NewDetail end) as NewAddress,
   max(case when TypeID = 9 then NewDetail end) as NewCity
into #temp
from Table1
group by PersonID, ChangeId, ChangeDateTime
;

请参阅Fiddle