2017-01-03 69 views
0

我試圖從SQL Server 2012中的列中解析某些逗號分隔值,同時仍然保留左側和右側列中的數據。SQL Server 2012逗號分析

我已經看到一些類似的主題解決方案,但似乎沒有什麼我正在尋找。

我有這樣的:

FirstName LastName userid Regions   ViewCosts HelpReviewCosts 
--------------------------------------------------------------------- 
Darron  Peters  ya00003 All    y   y 
John  Davies  ya30982 NA, EM, AP, LA  n   n 

我試圖解析地區列,以便我能得到這個:

FirstName LastName userid Regions   ViewCosts HelpReviewCosts 
--------------------------------------------------------------------- 
Darron  Peters  ya00003 All    y   y 
John  Davies  ya30982 NA     n   n 
John  Davies  ya30982 EM     n   n 
John  Davies  ya30982 AP     n   n 
John  Davies  ya30982 LA     n   n 
+1

的[SQL服務器分割成CSV多行]可能的複製(http://stackoverflow.com/questions/9811161/sql-server-split-csv-into-multiple-rows) – GurV

+4

爲什麼不修復設計問題呢?使用*分開的*表將人員與地區聯繫起來。你在這裏展示的甚至是第一範式。一旦你有了這個,以你想要的形式檢索數據需要一個簡單的JOIN –

+0

如果你有數據庫模式的控制,你應該規範化數據,而不是存儲一個CSV列表。 –

回答

2

有成千上萬的關於如何分割/解析字符串的例子。以下是兩個樣本,一個是UDF,另一個是沒有。無論使用CROSS APPLY

隨着UDF

Declare @Yourtable table (FirstName varchar(25) ,LastName varchar(25),userid varchar(25), Regions varchar(50), ViewCosts varchar(25), HelpReviewCosts varchar(25)) 
Insert Into @Yourtable values 
('Darron','Peters','ya00003','All','y','y'), 
('John','Davies','ya30982','NA, EM, AP, LA','n','n') 

Select A.FirstName 
     ,A.LastName  
     ,A.userid 
     ,Regions =B.RetVal 
     ,A.ViewCosts 
     ,A.HelpReviewCosts 
From @Yourtable A 
Cross Apply [dbo].[udf-Str-Parse](A.Regions,',') B 

沒有一個UDF

Select A.FirstName 
     ,A.LastName  
     ,A.userid 
     ,Regions =B.RetVal 
     ,A.ViewCosts 
     ,A.HelpReviewCosts 
From @Yourtable A 
Cross Apply ( 
       Select RetSeq = Row_Number() over (Order By (Select null)) 
         ,RetVal = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)'))) 
       From (Select x = Cast('<x>'+ replace((Select A.Regions as [*] For XML Path('')),',','</x><x>')+'</x>' as xml).query('.')) as A 
       Cross Apply x.nodes('x') AS B(i) 
    ) B 

兩個返回

enter image description here

如果需要

CREATE FUNCTION [dbo].[udf-Str-Parse] (@String varchar(max),@Delimiter varchar(10)) 
Returns Table 
As 
Return ( 
    Select RetSeq = Row_Number() over (Order By (Select null)) 
      ,RetVal = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)'))) 
    From (Select x = Cast('<x>'+ replace((Select @String as [*] For XML Path('')),@Delimiter,'</x><x>')+'</x>' as xml).query('.')) as A 
    Cross Apply x.nodes('x') AS B(i) 
); 
--Select * from [dbo].[udf-Str-Parse]('Dog,Cat,House,Car',',') 
--Select * from [dbo].[udf-Str-Parse]('John Cappelletti was here',' ') 
--Select * from [dbo].[udf-Str-Parse]('this,is,<test>,for,< & >',',') 
0

我建議你使用STRING_SPLIT功能

WITH 
CTE_Sample AS 
(
    SELECT 'All'   AS txt 
    UNION ALL 
    SELECT 'NA, EM, AP, LA' AS txt 
) 

SELECT 
    txt, 
    value 
    FROM CTE_Sample 
    CROSS APPLY STRING_SPLIT(txt, ','); 
0

如果你不想給UDF「UDF '和'string_split'函數,那麼你可以使用這個query.and它適用於大型逗號分隔的字符串,也快得多比別人...

`CREATE TABLE TB (Number INT) 
DECLARE @I INT=0 
WHILE @I<1000 
BEGIN 
INSERT INTO TB VALUES (@I) 
SET @[email protected]+1 
END 
SELECT 
    FirstName 
    ,LastName 
    ,userid 
    ,S_DATA 
    ,ViewCosts 
    ,HelpReviewCosts 
FROM (
    SELECT 
      FirstName 
      ,LastName 
      ,userid 
      ,CASE WHEN LEN(LIST2)>0 THEN LTRIM(RTRIM(SUBSTRING(LIST2, NUMBER+1, CHARINDEX(',', LIST2, NUMBER+1)-NUMBER - 1))) 
        ELSE NULL 
      END AS S_DATA 
      ,ViewCosts 
      ,HelpReviewCosts 
      ,NUMBER 
    FROM(
     SELECT FirstName 
       ,LastName 
       ,userid 
       ,','+Regions+',' LIST2 
       ,ViewCosts 
       ,HelpReviewCosts 
       FROM Tb1 
     )DT 
     LEFT OUTER JOIN TB N ON (N.NUMBER < LEN(DT.LIST2)) OR (N.NUMBER=1 AND DT.LIST2 IS NULL) 
     WHERE SUBSTRING(LIST2, NUMBER, 1) = ',' OR LIST2 IS NULL 
    ) DT2 
    WHERE S_DATA<>'' 

this is my Output