2011-02-25 12 views
20

J'ai un problème lors de la division de valeurs de colonne unique en plusieurs valeurs de colonne.Comment diviser une seule colonne en plusieurs valeurs de colonne?

Par exemple:

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

et j'ai besoin de quelque chose de sortie comme ceci:

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

Le nom du milieu peut être omis (pas besoin d'un prénom) Les colonnes sont déjà créées et besoin d'insérer les données de cette seule colonne Name.

+0

Est-ce quelque chose que vous voulez faire dans SQL Server? Dans une instruction SELECT? Dans une instruction 'INSERT' ou' UPDATE'? Plus de détails nous aiderait à répondre à votre question – BinaryTox1n

+0

qui est terrible conception pour le stockage de nom, vous devriez envisager d'avoir premier, dernier, deuxième prénom en colonnes séparées, J'espère que vous ne faites aucun rapport sur cette table qui divise les noms que vous avez demandé –

+0

Besoin de cela dans une déclaration choisie. En fait, c'est pour la procédure stockée qui insère les données en sélectionnant les valeurs d'une table.Alors je l'obtiens dans l'instruction select qui sera géniale ... – Shahsra

Répondre

18

Votre approche ne traitera pas beaucoup de noms correctement, mais ...

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

Je reçois l'erreur: # 1305 - FUNCTION preprodshem.Charindex n'existe pas. après une recherche, j'ai trouvé que cette fonction n'est pas supportée par mysql, et j'ai besoin de quelques changements en utilisant: SUBSTRING_INDEX pour résoudre ça. – Mimouni

+2

@IlyasMimouni - cette question est étiquetée SQL Server. –

2

Ce dont vous avez besoin est une fonction définie par l'utilisateur. Avec cela, la solution ressemble

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 

est ici une fonction split exemple:

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

Une alternative à Martin

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

Échantillon Table

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

Donc, cette requête fonctionne pour des millions de valeurs dans cette colonne, je suppose que oui .... – Shahsra

+1

@Shahsra - Oui. Par définition SQL est un langage basé sur SET donc ce que vous faites sur un enregistrement est fait sur tous les enregistrements de manière égale. – RichardTheKiwi

+0

Cela semble juste donner le prénom deux fois en ce moment? –

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 

et aussi vérifier le lien ci-dessous pour référence

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

0

Voici comment je l'ai fait sur une base de données SQLite:

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

espère que ce aide.

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