2009-10-30 17 views
0

使用状态作为一个例子,我现在的数据看起来像在SQL中,我可以将“|”将ID列表分隔到其值的列表中?

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和吐出逗号分隔的列表,我只需要列表,但是我有更多的表格,所以我正在寻找一个更干净的解决方案。 谢谢!

+0

这是一个常见的问题,只是代替 '管' 逗号'。我会谷歌和搜索堆栈溢出像'sql split逗号'。 – 2009-10-30 20:56:07

+0

这不是真的一样,我熟悉如何分割值,或生成一个逗号分隔列表。在这种情况下,我正在寻找用实际值替换ID。到目前为止,我想不出一种不涉及编写函数的方式。 – PBG 2009-10-30 21:04:21

回答

1

我用下面的UDF来处理拆分(通过4guysfromrolla

set ANSI_NULLS ON 
set QUOTED_IDENTIFIER ON 
GO 
CREATE FUNCTION [dbo].[Split] 
(
    @List nvarchar(2000), 
    @SplitOn nvarchar(5) 
) 
RETURNS @RtnValue table 
(  
    Id int identity(1,1), 
    Value nvarchar(100) 
) 
AS 
BEGIN 
    While (Charindex(@SplitOn,@List)>0) 
    Begin 
     Insert Into @RtnValue (value) 
     Select 
      Value = ltrim(rtrim(Substring(@List,1,Charindex(@SplitOn,@List)-1))) 
     Set @List = Substring(@List,Charindex(@SplitOn,@List)+len(@SplitOn),len(@List)) 
    End 

    Insert Into @RtnValue (Value) 
    Select Value = ltrim(rtrim(@List)) 

    Return 
END 

以下是UDF如何使用的例子:

select [Value] from [dbo].Split('CA|NY|VA', '|') 

这将返回您提供3种表在其中的行,每个州的一个。

UPDATE:

这里是整个呼叫做翻译第一:

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 

让我知道,如果您有需要更新什么,使这项工作与你的表格,而任何疑问比我的测试表。

+0

但我不需要3行,我需要它保持逗号分隔的列表,只是具有不同的值。 – PBG 2009-10-30 21:16:47

+0

所以使用这个函数来分隔,创建另一个函数来获取实际值,并将结果连接到第一个结果字段中。我没有看到用本地方式做到这一点。 – 2009-10-30 21:38:40

0

我想出了以下,但我不得不使用临时表来做到这一点;由于某种原因,子查询不适用于SUBSTRING。

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 
0

这里是它采用了Numbers表格,XML和CROSS APPLY(两次),非UDF的解决方案:

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) 
相关问题