在一列中显示多个值到单行

时间:2011-08-11 11:29:17

标签: sql-server sql-server-2008

我的下表有coulmn cityname,operatorname和prefix: - 前缀列包含多个值,范围为。

Cityname operatorname     prefix
-------- ---------------- -----------------------------------------------------------
Kolkata  Unitech          90620-90629 82960-82969
Kolkata  Datacom          90730-90739
Kolkata  BSNL             94330-94339 94320-94325
Kolkata  Loop             91100-91109
Kolkata  Reliance Telecom 98830-98839 96810-96819 88200-88209
Mumbai   BPL Mobile       98210-98219 96640-96649 97730-97739 98700-98709 80820-80829
Mumbai   Bharti Airtel    98670-98679 98920-98929 99670-99674 99870-99878 90040-90049

但是我希望新行上的每个preix也有例如... 91100-91109意味着范围从91100,91101 91102 91103 .....至91109 ..

belwo是我想要的输出,例如kolkata Unitech Wireless

Cityname  operatorname      prefix 
--------  ----------------  ------
Kolkata   Unitech Wireless  90620
Kolkata   Unitech Wireless  90621
Kolkata   Unitech Wireless  90622
Kolkata   Unitech Wireless  90623
.....
.....
.....
Kolkata   Unitech Wireless  90629
Kolkata   Unitech Wireless  82960
Kolkata   Unitech Wireless  82961
Kolkata   Unitech Wireless  82962
.....
.....
.....
Kolkata   Unitech Wireless  82969

然后是kolkata数据通信解决方案等等......

请在Sql server 2008中写下查询需要帮助

请尽早建议。

1 个答案:

答案 0 :(得分:3)

我可以通过两个逻辑步骤看到这个问题:

  1. 将每个前缀范围列表拆分为一组前缀范围,即每一行,如

    city operator prefix-range1 prefix-range2 prefix-range3 …

    分为

    city operator prefix-range1
    city operator prefix-range2
    city operator prefix-range3
    city

  2. 展开每个前缀范围项目,如

    city operator Prefix1-PrefixN

    进入一系列这样的行:

    city operator Prefix1
    city operator Prefix2
    city operator
    city operator PrefixN-1
    city operator PrefixN

  3. 以下是尝试实现上述逻辑:

    WITH data (Cityname, operatorname, prefix) AS (  /* this is just a sample data definition */
      SELECT 'Kolkata', 'Unitech         ', '90620-90629 82960-82969' UNION ALL
      SELECT 'Kolkata', 'Datacom         ', '90730-90739' UNION ALL
      SELECT 'Kolkata', 'BSNL            ', '94330-94339 94320-94325' UNION ALL
      SELECT 'Kolkata', 'Loop            ', '91100-91109' UNION ALL
      SELECT 'Kolkata', 'Reliance Telecom', '98830-98839 96810-96819 88200-88209' UNION ALL
      SELECT 'Mumbai ', 'BPL Mobile      ', '98210-98219 96640-96649 97730-97739 98700-98709 80820-80829' UNION ALL
      SELECT 'Mumbai ', 'Bharti Airtel   ', '98670-98679 98920-98929 99670-99674 99870-99878 90040-90049'
    ),
    SplitGroups AS (  /* this is where the list is split into separate ranges */
      SELECT
        d.Cityname, d.operatorname,
        StartPrefix = CAST(LEFT (x.PrefixGroup, 5) AS int),
        EndPrefix   = CAST(RIGHT(x.PrefixGroup, 5) AS int)
      FROM (
        SELECT
          Cityname, operatorname,
          prefixlist = CAST('<i>'+REPLACE(prefix, ' ', '</i><i>')+'</i>' AS xml)
        FROM data
      ) d
      CROSS APPLY (
        SELECT
          i.value('.', 'varchar(max)') AS PrefixGroup
        FROM d.prefixlist.nodes('i') x (i)
      ) x
    )
    SELECT  /* the final SELECT expands the ranges into single prefix rows */
      g.Cityname, g.operatorname,
      prefix = g.StartPrefix + v.number
    FROM SplitGroups g
      INNER JOIN master..spt_values v on v.type = 'P'
        AND v.number BETWEEN 0 AND g.EndPrefix - g.StartPrefix
    

    它在我的SQL Server 2008 R2中按预期工作,但已做出以下假设:

    1. 所有原始prefix值的格式均匀一致:

      • 范围由单个空格分隔;

      • 除了区分范围之外没有空格;

      • 每个范围都是一个整数,后跟一个连字符(-),后跟一个整数。

    2. 每个整数(前缀)恰好包含5位数字。

    3. 每个范围不超过2048个前缀,即结束前缀和起始前缀之间的差异永远不会超过2047.这是master..spt_values表的限制。如果您需要支持范围内超过2048个前缀,则可以使用自己的数字表替换它。


    4. 参考文献: