2009-10-30 45 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) 
相關問題