2014-08-28 42 views
0

我想通过拆分它们的源代码来将一些数据导入到mssql视图中。我有一些列中的电话号码存储为逗号分隔值(每个包含一个手机联系人)。我需要与每个“电话联系人”合作,所以我希望每个人都能看到他们。而且每一行都必须包含来自拆分的联系人的顺序。将表列中的逗号分隔值分隔成使用mssql的行?

来源:

Department | SaleMngrs | Operators  | Secretary 
---------------------------------------------------------- 
'Technics' | '123,456,77'| '+122,Line 1' | '77889,112' 
'Development'| '123,3366' | null   | 'Lines 7-8' 

正如可以看到的,逗号分隔值是一团糟,但spliter是,(逗号)。

通缉的结果:

Department | TypeOfContact | Contact | ContactOrder 
------------------------------------------------------ 
'Technics' | 'SalesManagers'| '123'  | 1 
'Technics' | 'SalesManagers'| '456'  | 2 
'Technics' | 'SalesManagers'| '77'  | 3 
'Technics' | 'Operators' | '+122'  | 1 
'Technics' | 'Operators' | 'Line 1' | 2 
'Technics' | 'Secretary' | '77889' | 1 
'Technics' | 'Secretary' | '112'  | 2 
'Development'| 'SalesManagers'| '123'  | 1 
'Development'| 'SalesManagers'| '3366'  | 2 
'Development'| 'Secretary' | 'Lines 7-8'| 1 

没有UDF或SP通缉。请给我一个SELECT

+1

你不能在单个select语句中做到这一点。 – 2014-08-28 16:32:30

+0

TypeOfContact在那里。第二列是SalesManagers,后面跟着运营商和秘书。 – 2014-08-28 16:38:40

+0

@Sean Lange我不明白你的意思是你的第二个评论... – procma 2014-08-28 16:47:55

回答

1

请尝试以下方法(它是作为数据结构一样漂亮) - 与UNPIVOT优化:

set nocount on 

declare @source table (Department varchar(50), SaleMngrs varchar(50), Operators varchar(50), Secretary varchar(50)); 

insert into @source values ('Technics' , '123,456,77', '+122,Line 1' , '77889,112'); 
insert into @source values ('Development', '123,3366' , null   , 'Lines 7-8'); 

;WITH cte (Department, TypeOfContact, Contact) 
AS 
(
    SELECT Department, TypeOfContact, cast('<Contact><c>' + replace(Contact,',','</c><c>') + '</c></Contact>' as xml) AS Contact 
    FROM (SELECT Department, SaleMngrs AS SalesManagers, Operators, Secretary FROM @source) p 
    UNPIVOT (Contact FOR TypeOfContact IN (SalesManagers, Operators, Secretary)) AS unpvt 
) 
Select Department 
    , TypeOfContact 
    , Contact.c.value('.','varchar(20)') AS Contact 
    , ROW_NUMBER() OVER (PARTITION BY Department, TypeOfContact ORDER BY Department, TypeOfContact) AS ContactOrder 
FROM cte CROSS APPLY Contact.nodes('/Contact/c') as Contact(c); 

输出

Department TypeOfContact Contact    ContactOrder 
------------ ------------- -------------------- -------------------- 
Development SalesManagers 123     1 
Development SalesManagers 3366     2 
Development Secretary  Lines 7-8   1 
Technics  Operators  +122     1 
Technics  Operators  Line 1    2 
Technics  SalesManagers 123     1 
Technics  SalesManagers 456     2 
Technics  SalesManagers 77     3 
Technics  Secretary  112     1 
Technics  Secretary  77889    2 

编辑:使用UN优化查询PIVOT(下原):

set nocount on 

declare @source table (Department varchar(50), SaleMngrs varchar(50), Operators varchar(50), Secretary varchar(50)); 

insert into @source values ('Technics' , '123,456,77', '+122,Line 1' , '77889,112'); 
insert into @source values ('Development', '123,3366' , null   , 'Lines 7-8'); 

;WITH cte (Department, SalesMngrs, Operators, Secretary) 
AS 
(
    select Department 
     , cast('<SaleMngrs><c>' + replace(SaleMngrs,',','</c><c>') + '</c></SaleMngrs>' as xml) AS SalesMngrs 
     , cast('<Operators><c>' + replace(Operators,',','</c><c>') + '</c></Operators>' as xml) AS Operators 
     , cast('<Secretary><c>' + replace(Secretary,',','</c><c>') + '</c></Secretary>' as xml) AS Secretary 
    from @source 
) 
Select Department 
    , TypeOfContact 
    , Contact 
    , ROW_NUMBER() OVER (PARTITION BY Department, TypeOfContact ORDER BY Department, TypeOfContact) AS ContactOrder 
FROM (
    Select Department, 'SalesManagers' AS TypeOfContact, SaleMngrs.c.value('.','varchar(20)') as Contact 
    from cte CROSS APPLY SalesMngrs.nodes('/SaleMngrs/c') as SaleMngrs(c) 
    union 
    Select Department, 'Operators', Operators.c.value('.','varchar(20)') 
    from cte CROSS APPLY Operators.nodes('/Operators/c') as Operators(c) 
    union 
    Select Department, 'Secretary', Secretary.c.value('.','varchar(20)') 
    from cte CROSS APPLY Secretary.nodes('/Secretary/c') as Secretary(c) 
) AS q; 
+0

我认为可以使用UNPIVOT优化此查询。 – wdosanjos 2014-08-29 11:36:56

0

马丁,

我知道你在一个SQL语句想要这个,但如果你创建一个函数,则SQL不会那么unpretty。

ALTER FUNCTION dbo.Split ( @InputString VARCHAR(8000), @Delimiter VARCHAR(50)) 
RETURNS @Items TABLE (Item VARCHAR(8000), Rowid INT) 
AS 
BEGIN 
     IF @Delimiter = ' ' 
     BEGIN 
      SET @Delimiter = ',' 
      SET @InputString = REPLACE(@InputString, ' ', @Delimiter) 
     END 

     IF (@Delimiter IS NULL OR @Delimiter = '') 
      SET @Delimiter = ',' 

     DECLARE @Item     VARCHAR(8000) 
     DECLARE @ItemList  VARCHAR(8000) 
     DECLARE @DelimIndex  INT 
     declare @rowseq   INT 

     SET @rowseq = 0 

     SET @ItemList = @InputString 
     SET @DelimIndex = CHARINDEX(@Delimiter, @ItemList, 0) 
     WHILE (@DelimIndex != 0) 
     BEGIN 
      SET @Item = SUBSTRING(@ItemList, 0, @DelimIndex) 
      SET @rowseq = @rowseq + 1 
      INSERT INTO @Items VALUES (@Item, @rowseq) 

      -- Set @ItemList = @ItemList minus one less item 
      SET @ItemList = SUBSTRING(@ItemList, @DelimIndex+1, LEN(@ItemList)[email protected]) 
      SET @DelimIndex = CHARINDEX(@Delimiter, @ItemList, 0) 
     END -- End WHILE 

     IF @Item IS NOT NULL -- At least one delimiter was encountered in @InputString 
     BEGIN 
      SET @Item = @ItemList 
      SET @rowseq = @rowseq + 1 
      INSERT INTO @Items VALUES (@Item, @rowseq) 
     END 

     -- No delimiters were encountered in @InputString, so just return @InputString 
     ELSE INSERT INTO @Items VALUES (@InputString, 1) 

     RETURN 

END 

上述功能,我从这个SO问题找到,但我做了一些修改,以它为您的方案。 How to split a comma-separated value to rows

然后你SQL会...

SELECT department, 'SalesManager' as TypeOfContract, s.Item as Contact , s.rowId 
FROM <YOUR TABLE> t 
    CROSS APPLY 
     (SELECT * FROM dbo.Split(t.SalesMngrs, ',') where item is not null) S 
UNION ALL 
SELECT department, 'Operators' as TypeOfContract, s.Item as Contact , s.rowId 
FROM <YOUR TABLE> t 

    CROSS APPLY 
     (SELECT * FROM dbo.Split(t.Operators, ',') where item is not null) S 
UNION ALL 
SELECT department, 'Secretary' as TypeOfContract, s.Item as Contact , s.rowId 
FROM <YOUR TABLE> t 
    CROSS APPLY 
     (SELECT * FROM dbo.Split(t.Secretary, ',') where item is not null) S  

我希望这有助于。

+0

Thanx @Ed Mendez,你有没有试过性能? @wdosanjos上面写的一个选择是好还是差? – procma 2014-08-29 07:50:14