从树结构表中,如何选择分支然后为每个分支分区更多信息

时间:2013-08-19 17:22:40

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

我有一个描述地理结构的表,它构建成树状结构,其中column1是'country',column2包含最大的管理区域'region1',然后'region2'列包含region1的子项等。

所以这个

                     r
     /               |               \
     1               2               3
/    |     \    /    |     \    /    |     \
11   12    13   21   22    23   31   32     33

对于每个不同的组合都代表这样:

cntry|  r1  |  r2
------------------
  r  |  1   |  11
  r  |  1   |  12
  r  |  1   |  13
  r  |  2   |  21
  r  |  2   |  22
  r  |  2   |  23
  r  |  3   |  31
  r  |  3   |  32
  r  |  3   |  33

此外,每个叶节点都包含一些可以跨越多行的附加信息。如邮政编码。因此表实际上看起来像这样:

cntry| r1   |  r2  |  zip |
--------------------------|
  r  |  1   |  11  |  a   |
  r  |  1   |  11  |  aa  |
  r  |  1   |  11  |  aaa |
  r  |  1   |  11  |  aaaa|
  r  |  1   |  12  |  b   |
  r  |  1   |  13  |  c   |
  r  |  1   |  13  |  cc  |
  r  |  1   |  13  |  ccc |
  r  |  2   |  21  |  d   |
  r  |  2   |  22  |  e   |
  r  |  2   |  22  |  ee  |
  r  |  2   |  23  |  f   |
  r  |  3   |  31  |  g   |
  r  |  3   |  31  |  gg  |
  r  |  3   |  31  |  ggg |
  r  |  3   |  32  |  h   |
  r  |  3   |  33  |  i   |

现在,真实表包含近200万行,地名列中有大量文本。这是附加行中的大量重复信息,其中只有邮政编码是新信息。它占用带宽而且速度很慢。

是否可以进行查询以明确地选择cntry,r1,r2,并且在其他列中使用null的每个不同行后面的zip行?因此,选择的结果将如下所示:

cntry| r1   |  r2  |  zip |
--------------------------|
  r  |  1   |  11  |  a   |
 NULL| NULL | NULL |  aa  |
 NULL| NULL | NULL |  aaa |
 NULL| NULL | NULL |  aaaa|
  r  |  1   |  12  |  b   |
  r  |  1   |  13  |  c   |
 NULL| NULL | NULL |  cc  |
 NULL| NULL | NULL |  ccc |
  r  |  2   |  21  |  d   |
  r  |  2   |  22  |  e   |
 NULL| NULL | NULL |  ee  |
  r  |  2   |  23  |  f   |
  r  |  3   |  31  |  g   |
 NULL| NULL | NULL |  gg  |
 NULL| NULL | NULL |  ggg |
  r  |  3   |  32  |  h   |
  r  |  3   |  33  |  i   |

1 个答案:

答案 0 :(得分:1)

with cte as (
   select *, row_number() over(partition by cntry, r1, r2 order by zip) as row_num
   from tbl
)
select
    case when c.row_num = 1 then cntry end as cntry,
    case when c.row_num = 1 then r1 end as r1,
    case when c.row_num = 1 then r2 end as r2,
    c.zip
from cte as c
order by c.r1, c.r2, row_num

sql fiddle demo