2011-02-25 252 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