简化CTE字符串连接?

问题描述 投票:3回答:2

我有以下代码清单

Code Meaning 
1    Single 
2    Married/Separate 
3    Divorced 
4    Widowed 
8    Not Applicable 
99   Not known

我试图使用CTE将这些展平为一行。我有一个CTE解决方案,它使用RowNumber函数来执行此操作。

WITH Flattened (JoinItem, CodeMeaning) AS
(
    SELECT 1 AS JoinItem, CAST('' AS VARCHAR(255))
    UNION ALL
    SELECT f.JoinItem+1, CAST(f.CodeMeaning + ',' + c.CodeMeaning AS VARCHAR(255))
    FROM
    (
        SELECT JoinItem = ROW_NUMBER() OVER (ORDER BY Code),c.Code + ' - ' + c.Meaning AS CodeMeaning
        FROM Codes c
    ) c
    INNER JOIN Flattened f
    ON f.JoinItem=c.JoinItem
)
SELECT TOP 1 JoinItem,  CodeMeaning 
FROM Flattened 
ORDER BY JoinItem DESC

但是,我想知道我是否可以在不使用RowNumber函数但仍使用CTE的情况下执行此操作。所以我有以下内容 - 我认为更简单 - Sql

WITH Flattened (JoinItem, CodeMeaning) AS
(
    SELECT 1 AS JoinItem, CAST('' AS VARCHAR(255))
    UNION ALL
    SELECT c.JoinItem, CAST(f.CodeMeaning + ',' + c.CodeMeaning AS VARCHAR(255))
    FROM
    (
        SELECT 1 AS JoinItem,c.Code + ' - ' + c.Meaning AS CodeMeaning
        FROM Codes c            
    ) c
    INNER JOIN Flattened f
    ON f.JoinItem=c.JoinItem
)
SELECT JoinItem, odeMeaning 
FROM Flattened 

现在它正在最大化递归并产生类似于笛卡尔联合的东西 - 如果不是更糟!

我想尝试让它每次使用固定的“JoinItem”加入锚记录

因此,如果有解决方案,任何指向我出错的地方都会有所帮助。

编辑SqlFiddle

sql sql-server-2008-r2 common-table-expression
2个回答
5
投票

假设这是SQL Server,你考虑过这样的事情:

select stuff((select ',' + c.code + '-' + c.Meaning
              from codes c
              order by code
              for xml path ('')
             ), 1, 1, '')

编辑:

要使用CTE执行此操作,请先定义序列号,然后执行展平:

with c as (
      select row_number() over (order by code) as seqnum, c.code + '-' + c.meaning as CodeMeaning
      from codes c
     ),
     flattened as (
      select CodeMeaning as CodeMeaning
      from c
      where rownum = 1
      union all
      select f.CodeMeaning + ',' + c.CodeMeaning
      from c join
           flattened f
           on c.seqnum = f.seqnum + 1
     )
select *
from flattened;

如果列表太长,则可能必须增加默认递归级别。


0
投票

如果没有ROW_NUMBER(),您的查询应该是

WITH Flattened (Code, CodeMeaning, lev) AS
(
    SELECT TOP 1 Code, CAST(CAST(Code AS VARCHAR(255)) + ' - ' + Meaning AS VARCHAR(255)),  0 AS lev FROM codes ORDER BY Code    
    UNION ALL
    SELECT c.Code, CAST(f.CodeMeaning + ',' + CAST(c.Code AS varchar(255))+ ' - ' + c.Meaning AS VARCHAR(255)), f.lev+1
    FROM codes c
    INNER JOIN Flattened f
    ON c.Code > f.Code
)
SELECT TOP 1 CodeMeaning  FROM Flattened ORDER BY lev DESC;

您也可以在最后一个选择中使用ORDER BY LEN(CodeMeaning)DESC。在这种情况下,lev(递归级别)列不是必需的。如果您对代码值有额外的了解,那么您可以使用更准确的INNER JOIN谓词来优化查询,例如ON f.Code <c.Code AND f.Code + 10> c.Code。

© www.soinside.com 2019 - 2024. All rights reserved.