在SQL中连接两个范围

时间:2014-05-07 22:21:04

标签: sql

这是我的表,

      ID#   | DocBreak |  Old Document Range | New Document Range
     00001  |   D      |  00001 - 00005   
     00002  |   N      |  00001 - 00005          
     00003  |   N      |  00001 - 00005     
     00004  |   D      |  00001 - 00005 
     00005  |   D      |  00001 - 00005 
     00006  |   D      |  00006 - 00006
     00007  |   N      |  00007 - 00007  
     00008  |   N      |  00008 - 00008
     00009  |   D      |  00009 - 00011           
     00010  |   N      |  00009 - 00011           
     00011  |   D      |  00009 - 00011           
     00012  |   N      |  00012 - 00012           

结果应该是:

      ID#   | DocBreak |  Old Document Range      | New Document Range
     00001  |   D      |  00001 - 00005           | 00001 - 00005 
     00002  |   N      |  00001 - 00005           |           
     00003  |   N      |  00001 - 00005           |    
     00004  |   D      |  00001 - 00005           | 00001 - 00005
     00005  |   D      |  00001 - 00005           | 00001 - 00005
     00006  |   D      |  00006 - 00006           | 00006 - 00006|00007 - 00007|00008 - 00008
     00007  |   N      |  00007 - 00007           | 
     00008  |   N      |  00008 - 00008           | 
     00009  |   D      |  00009 - 00011           | 00009 - 00011
     00010  |   N      |  00009 - 00011           | 
     00011  |   D      |  00009 - 00011           | 00009 - 00011|00012 - 00012  
     00012  |   N      |  00012 - 00012           | 

如果有人可以帮我弄清楚如何从DocBreak和Old Document Range列生成新文档范围,那会很好。

感谢。

1 个答案:

答案 0 :(得分:0)

更新

SQL Fiddle

With AllDocs As (
  Select ID, DOCBREAK, OLDDOCUMENTRANGE 
  From Test),

UniqueDocRanges as (
  Select DISTINCT AllDocs.ID, AllDocs.DOCBREAK, t.OLDDOCUMENTRANGE
  From Test t
  INNER JOIN AllDocs on t.Id >= AllDocs.ID
                    AND t.ID < (Select Case When min(ID) Is not Null Then min(ID) else (select max(ID) + 1 from Test) End from Test where Test.Id > AllDocs.ID and Test.DocBreak = 'D')  
  )
select AllDocs.*, Case When DocBreak = 'N' Then '' Else STUFF((
    SELECT ' | ' + t.OLDDocumentRange
    FROM UniqueDocRanges t
    WHERE t.Id = AllDocs.ID
    FOR XML PATH('')
),1,3, '') End AS ConcatenatedDocs
from AllDocs 
;

以上与下面的示例类似,但我发现更具可读性,并且还有删除重复项的额外好处。 AllDocs就像它所说的所有文档列表(D&amp; N)。 UniqueDocRanges正在获取AllDocs列表并找到每个ID的Docs组,以DocBreak-D开头,直到下一个D,其中包含所有N&。 UniqueDocRanges中的DISTINCT运算符删除重复项。最后,最后一个语句获取所有文档的列表,连接在我们的组中,然后将它们连接起来形成我们的CONCATENATEDDOCS列。

希望对你有用!


花了很多时间在这上面。享受!

SELECT tOuter.*, Case When DocBreak = 'N' Then '' Else STUFF((
    SELECT ' | ' + t.OLDDocumentRange
    FROM Test t
    WHERE t.Id >= tOuter.ID
    AND t.ID < (Select 
                 Case When min(ID) Is not Null Then min(ID) 
                 else 
                    (select max(ID) + 1 from Test) 
                 End 
                from Test where Test.Id > tOuter.ID and Test.DocBreak = 'D')
    FOR XML PATH('')
),1,3, '') End AS ConcatenatedDocs
FROM Test tOuter

我创建了一个SQLFiddle演示。它假定您使用的是SQL Server。如果你不是你可以使用类似的技术,而是换掉你的RDBMS使用的连接。

它实质上是对表中的每一行进行相关的子查询,并将所有行都放到DocBreak =&#34; D&#34;的下一行。其中的所有行都使用FOR XML PATH(&#39;&#39;)技巧与|连接。 Stuff命令摆脱了第一个不需要的管道。