在SQL中,我可以将“|”分隔的ID列表转换为它们的值列表吗?

在SQL中,我可以将“|”分隔的ID列表转换为它们的值列表吗?,sql,sql-server,tsql,Sql,Sql Server,Tsql,以状态为例,我当前的数据如下 StateAbbrev | NumOfResults ----------- ------------ MD | 5 VA | 2 DC | 7 MD|VA | 2 CA|NY|VA | 1 我希望它输出以下内容 StateName | NumOfResults --------- -------

以状态为例,我当前的数据如下

StateAbbrev  | NumOfResults
-----------    ------------
MD           | 5
VA           | 2
DC           | 7
MD|VA        | 2
CA|NY|VA     | 1
我希望它输出以下内容

StateName                    | NumOfResults
---------                      ------------
Maryland                     | 5
Virginia                     | 2
District of Columbia         | 7
Maryland,Virginia            | 2
California,New York,Virginia | 1
我有一个表可以将StateAbbrev映射到StateName

我可以创建一个函数,如果使用管道分隔ID,只需要获取列表,并吐出一个逗号分隔的列表,但是在这种情况下,我有不止一个表,所以我正在寻找一个更干净的解决方案。
谢谢大家!

我使用以下UDF通过

以下是如何使用自定义项的示例:

select [Value] from [dbo].Split('CA|NY|VA', '|')
这将返回一个包含3行的表,每个州一行

更新:

以下是首先进行翻译的完整要求:

declare @cslist varchar(2056)
select @cslist = coalesce(@cslist+',', '') + translated_states.full_state
FROM (

    select T2.full_state from [dbo].Split('CA|NY|VA', '|') as T1
    JOIN test as T2
    on T2.abbr_state = T1.[Value]

) translated_states
select @cslist

如果您对需要更新哪些内容才能使用您的表而不是我的测试表有任何疑问,请告诉我。

您可以编写一个C函数,然后使用SQLCLR执行此操作:


或者,您也可以编写一个T-SQL函数来实现这一点

我想出了以下方法,但我必须使用临时表来完成;由于某些原因,子查询无法与子字符串一起使用

DECLARE @T TABLE ( col VARCHAR(1000) )

INSERT  INTO @T
        ( col 
        )
        SELECT  'MD'
        UNION ALL
        SELECT  'MD|CA'
        UNION ALL
        SELECT  'MD|CA|VA'

DECLARE @states TABLE
    (
      abbr VARCHAR(2) ,
      StateName VARCHAR(10)
    )

INSERT  INTO @states
        SELECT  'MD' ,
                'Maryland'
        UNION ALL
        SELECT  'CA' ,
                'California'
        UNION ALL
        SELECT  'VA' ,
                'Virginia'



SELECT  col ,
        word = SUBSTRING('|' + col + '|', Number + 1,
                         CHARINDEX('|', '|' + col + '|', Number + 1) - Number
                         - 1) ,
        Number
INTO    #tmp
FROM    ( SELECT /*use a table of numbers if you have one instead of this subquery*/
                    ROW_NUMBER() OVER ( ORDER BY ( ac1.Object_ID ) ) AS Number
          FROM      Master.sys.columns ac1
        ) Numbers
        CROSS APPLY @t t
WHERE   Number >= 1
        AND Number < LEN('|' + col + '|') - 1
        AND SUBSTRING('|' + col + '|', Number, 1) = '|'
ORDER BY col ,
        Number

SELECT  t1.col ,
        StateName = REPLACE(( SELECT    StateName AS [data()]
                              FROM      #tmp t
                                        JOIN @states s ON t.word = s.abbr
                              WHERE     t1.col = t.col
                              ORDER BY  COL ,
                                        Number
                            FOR
                              XML PATH('')
                            ), ' ', '|')
FROM    #tmp t1



DROP TABLE #tmp

这是一个非UDF解决方案,它使用数字表、XML和交叉应用两次:

DECLARE @Numbers TABLE (Num INT);

INSERT INTO @Numbers VALUES (1);
INSERT INTO @Numbers VALUES (2);
INSERT INTO @Numbers VALUES (3);
INSERT INTO @Numbers VALUES (4);
INSERT INTO @Numbers VALUES (5);
INSERT INTO @Numbers VALUES (6);
INSERT INTO @Numbers VALUES (7);
INSERT INTO @Numbers VALUES (8);
INSERT INTO @Numbers VALUES (9);

DECLARE @Results TABLE (StateAbbrevs VARCHAR(255), NumOfResults INT);

INSERT INTO @Results VALUES ('MD', 5);
INSERT INTO @Results VALUES ('VA', 2);
INSERT INTO @Results VALUES ('DC', 7);
INSERT INTO @Results VALUES ('MD|VA', 2);
INSERT INTO @Results VALUES ('CA|NY|VA', 1);

DECLARE @Abbrev TABLE (StateAbbrev VARCHAR(2), StateName VARCHAR(255));

INSERT INTO @Abbrev VALUES ('MD', 'Maryland');
INSERT INTO @Abbrev VALUES ('VA', 'Virginia');
INSERT INTO @Abbrev VALUES ('DC', 'District of Columbia');
INSERT INTO @Abbrev VALUES ('CA', 'California');
INSERT INTO @Abbrev VALUES ('NY', 'New York');

--SELECT * FROM @Results;
--
--SELECT * FROM @Abbrev;

SELECT  STUFF(StateNames, 1, 1, '') AS StateNames,
        NumOfResults
FROM    @Results AS RESULTS0
        CROSS APPLY ( SELECT    ',' + ABBREV.StateName
                      FROM      ( SELECT    PVT.StateAbbrev,
                                            RESULTS.StateAbbrevs
                                  FROM      @Results AS RESULTS
                                            CROSS APPLY ( SELECT    SUBSTRING(RESULTS.StateAbbrevs, NUMBERS.Num, CHARINDEX('|', RESULTS.StateAbbrevs + '|', NUMBERS.Num) - NUMBERS.Num) AS StateAbbrev
                                                          FROM      @Numbers AS NUMBERS
                                                          WHERE     NUMBERS.Num <= LEN(RESULTS.StateAbbrevs)
                                                                    AND SUBSTRING('|' + RESULTS.StateAbbrevs, NUMBERS.Num, 1) = '|'
                                                        ) AS PVT
                                ) AS X
                                LEFT JOIN @Abbrev AS ABBREV ON ABBREV.StateAbbrev = X.StateAbbrev
                      WHERE     StateAbbrevs = RESULTS0.StateAbbrevs
                    FOR
                      XML PATH('')
                    ) AS Y ( StateNames )

这是一个常见的问题,只是用逗号而不是管道。我会在谷歌上搜索堆栈溢出,寻找类似“sql分割逗号”的东西。其实不一样,我熟悉如何分割值,或者生成逗号分隔的列表。在本例中,我希望用实际值替换ID。到目前为止,我想不出一种不需要编写函数的方法。但是我不需要3行,我需要它保持一个逗号分隔的列表,只是有不同的值。所以使用这个函数来分隔,创建另一个函数来获取实际值,并将结果集中到第一个结果字段中。我看不到一种方法可以在本地实现这一点。
DECLARE @Numbers TABLE (Num INT);

INSERT INTO @Numbers VALUES (1);
INSERT INTO @Numbers VALUES (2);
INSERT INTO @Numbers VALUES (3);
INSERT INTO @Numbers VALUES (4);
INSERT INTO @Numbers VALUES (5);
INSERT INTO @Numbers VALUES (6);
INSERT INTO @Numbers VALUES (7);
INSERT INTO @Numbers VALUES (8);
INSERT INTO @Numbers VALUES (9);

DECLARE @Results TABLE (StateAbbrevs VARCHAR(255), NumOfResults INT);

INSERT INTO @Results VALUES ('MD', 5);
INSERT INTO @Results VALUES ('VA', 2);
INSERT INTO @Results VALUES ('DC', 7);
INSERT INTO @Results VALUES ('MD|VA', 2);
INSERT INTO @Results VALUES ('CA|NY|VA', 1);

DECLARE @Abbrev TABLE (StateAbbrev VARCHAR(2), StateName VARCHAR(255));

INSERT INTO @Abbrev VALUES ('MD', 'Maryland');
INSERT INTO @Abbrev VALUES ('VA', 'Virginia');
INSERT INTO @Abbrev VALUES ('DC', 'District of Columbia');
INSERT INTO @Abbrev VALUES ('CA', 'California');
INSERT INTO @Abbrev VALUES ('NY', 'New York');

--SELECT * FROM @Results;
--
--SELECT * FROM @Abbrev;

SELECT  STUFF(StateNames, 1, 1, '') AS StateNames,
        NumOfResults
FROM    @Results AS RESULTS0
        CROSS APPLY ( SELECT    ',' + ABBREV.StateName
                      FROM      ( SELECT    PVT.StateAbbrev,
                                            RESULTS.StateAbbrevs
                                  FROM      @Results AS RESULTS
                                            CROSS APPLY ( SELECT    SUBSTRING(RESULTS.StateAbbrevs, NUMBERS.Num, CHARINDEX('|', RESULTS.StateAbbrevs + '|', NUMBERS.Num) - NUMBERS.Num) AS StateAbbrev
                                                          FROM      @Numbers AS NUMBERS
                                                          WHERE     NUMBERS.Num <= LEN(RESULTS.StateAbbrevs)
                                                                    AND SUBSTRING('|' + RESULTS.StateAbbrevs, NUMBERS.Num, 1) = '|'
                                                        ) AS PVT
                                ) AS X
                                LEFT JOIN @Abbrev AS ABBREV ON ABBREV.StateAbbrev = X.StateAbbrev
                      WHERE     StateAbbrevs = RESULTS0.StateAbbrevs
                    FOR
                      XML PATH('')
                    ) AS Y ( StateNames )