2011-02-25 484 views
20

我有一個問題,將單個列值拆分爲多個列值。如何將單個列值拆分爲多個列值?

例如:

Name 
------------ 
abcd efgh 
ijk lmn opq 
asd j. asdjja 
asb (asdfas) asd 
asd 

,我需要的輸出是這樣的:

first_name    last_name 
---------------------------------- 
abcd      efgh 
ijk      opq 
asd      asdjja 
asb      asd 
asd      null 

可以省略中間名(無需中間名)的列已經創建並需要插入單個Name列中的數據。

+0

這是你想在SQL Server中做的事嗎?在一個'SELECT'語句中?在INSERT或UPDATE語句中?更多細節可以幫助我們回答你的問題 – BinaryTox1n 2011-02-25 22:58:07

+0

這是名字存儲的糟糕設計,你應該考慮把第一個,最後一個,中間名作爲單獨的列,我希望你不要在這個表中做任何報告,按照你的要求拆分名字 – 2011-02-25 22:58:59

+0

需要在選擇語句中。其實它是存儲過程,它是通過從表中選擇值插入數據。所以我得到它在選擇語句,將是偉大的... – Shahsra 2011-02-25 23:00:37

回答

18

你的方法不會很多名字正確對待,但...

SELECT CASE 
     WHEN name LIKE '% %' THEN LEFT(name, Charindex(' ', name) - 1) 
     ELSE name 
     END, 
     CASE 
     WHEN name LIKE '% %' THEN RIGHT(name, Charindex(' ', Reverse(name)) - 1) 
     END 
FROM YourTable 
+0

我得到的錯誤:#1305 - 功能preprodshem.Charindex不存在。經過一番搜索,我發現這個函數不被mysql支持,並且需要使用一些改變:SUBSTRING_INDEX來解決這個問題。 – Mimouni 2016-09-21 10:09:02

+2

@IlyasMimouni - 這個問題被標記爲SQL Server。 – 2016-09-21 10:41:55

2

你需要的是一個分離的用戶定義函數。就這樣,該解決方案看起來像

With SplitValues As 
    (
    Select T.Name, Z.Position, Z.Value 
     , Row_Number() Over (Partition By T.Name Order By Z.Position) As Num 
    From Table As T 
     Cross Apply dbo.udf_Split(T.Name, ' ') As Z 
    ) 
Select Name 
    , FirstName.Value 
    , Case When ThirdName Is Null Then SecondName Else ThirdName End As LastName 
From SplitValues As FirstName 
    Left Join SplitValues As SecondName 
     On S2.Name = S1.Name 
      And S2.Num = 2 
    Left Join SplitValues As ThirdName 
     On S2.Name = S1.Name 
      And S2.Num = 3 
Where FirstName.Num = 1 

這裏是一個樣本分割功能:

Create Function [dbo].[udf_Split] 
( 
    @DelimitedList nvarchar(max) 
    , @Delimiter nvarchar(2) = ',' 
) 
RETURNS TABLE 
AS 
RETURN 
    (
    With CorrectedList As 
     (
     Select Case When Left(@DelimitedList, Len(@Delimiter)) <> @Delimiter Then @Delimiter Else '' End 
      + @DelimitedList 
      + Case When Right(@DelimitedList, Len(@Delimiter)) <> @Delimiter Then @Delimiter Else '' End 
      As List 
      , Len(@Delimiter) As DelimiterLen 
     ) 
     , Numbers As 
     (
     Select TOP(Coalesce(DataLength(@DelimitedList)/2,0)) Row_Number() Over (Order By c1.object_id) As Value 
     From sys.columns As c1 
      Cross Join sys.columns As c2 
     ) 
    Select CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen As Position 
     , Substring (
        CL.List 
        , CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen  
        , CharIndex(@Delimiter, CL.list, N.Value + 1)       
         - (CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen) 
        ) As Value 
    From CorrectedList As CL 
     Cross Join Numbers As N 
    Where N.Value <= DataLength(CL.List)/2 
     And Substring(CL.List, N.Value, CL.DelimiterLen) = @Delimiter 
    ) 
13

的替代馬丁的

select LEFT(name, CHARINDEX(' ', name + ' ') -1), 
     STUFF(name, 1, Len(Name) +1- CHARINDEX(' ',Reverse(name)), '') 
from somenames 

樣品表

create table somenames (Name varchar(100)) 
insert somenames select 'abcd efgh' 
insert somenames select 'ijk lmn opq' 
insert somenames select 'asd j. asdjja' 
insert somenames select 'asb (asdfas) asd' 
insert somenames select 'asd' 
insert somenames select '' 
insert somenames select null 
+0

因此,這個查詢適用於該列中的數百萬個值,我猜對了...... – Shahsra 2011-02-25 23:16:00

+1

@Shahsra - 是的。根據定義,SQL是一種基於SET的語言,因此您在一條記錄上所做的操作同樣在所有記錄上完成。 – RichardTheKiwi 2011-02-25 23:18:51

+0

這似乎只是在此刻給出兩個名字? – 2011-02-25 23:21:32

2
;WITH Split_Names (Name, xmlname) 
AS 
(
    SELECT 
    Name, 
    CONVERT(XML,'<Names><name>' 
    + REPLACE(Name,' ', '</name><name>') + '</name></Names>') AS xmlname 
     FROM somenames 
) 

SELECT  
xmlname.value('/Names[1]/name[1]','varchar(100)') AS first_name,  
xmlname.value('/Names[1]/name[2]','varchar(100)') AS last_name 
FROM Split_Names 

,並檢查下面的參考鏈接

http://jahaines.blogspot.in/2009/06/converting-delimited-string-of-values.html

0

下面是我這究竟是怎麼一個SQLite數據庫:

SELECT SUBSTR(name, 1,INSTR(name, " ")-1) as Firstname, SUBSTR(name, INSTR(name," ")+1, LENGTH(name)) as Lastname FROM YourTable;

希望它幫助。

0
SELECT 
    SUBSTRING_INDEX(SUBSTRING_INDEX(rent, ' ', 1), ' ', -1) AS currency, 
    SUBSTRING_INDEX(SUBSTRING_INDEX(rent, ' ', 3), ' ', -1) AS rent 
FROM tolets