如何组合多列中的值并使用transact sql

时间:2016-12-28 16:38:58

标签: sql-server tsql

我在sql server数据库中有一个表,其中包含四列电子邮件地址,即Email1,Email2,Email3Email4。我需要创建一个函数来返回合并的电子邮件地址并删除任何重复的电子邮件

(例如,Email1和Email3可能具有相同的地址email@email.com,我只需要在组合字符串中包含一次)。

我编写了一个如下功能,它会返回组合值,但不确定我们如何删除重复的电子邮件。

Create FUNCTION [dbo].[CombineAndCommaSeparateEmails] 

(@Email1 VARCHAR(250),@Email2 VARCHAR(250),@Email3 VARCHAR(250),@Email4 VARCHAR(250))

RETURNS VARCHAR(250)

AS BEGIN

DECLARE @combinedEmails VARCHAR(1000)

Set @combinedEmails=   
concat(
Rtrim(Ltrim(Case when @EMAIL1 is not null then @EMAIL1+',' end)),
Rtrim(Ltrim(Case when @EMAIL2 is not null then @EMAIL2+',' end)),
Rtrim(Ltrim(Case when @EMAIL3 is not null then @EMAIL3+',' end)),
Rtrim(Ltrim(@EMAIL4)))


Set @combinedEmails=   case 
when RIGHT(@combinedEmails,1)=',' then substring(@combinedEmails,1,len(@combinedEmails)-1)
else @combinedEmails END    

RETURN @combinedEmails
END

有什么想法吗?感谢

4 个答案:

答案 0 :(得分:2)

您可以使用var array1 = ['a','b','c','d']; var array2 = ['d','v','n','a','i','f']; 获取OUTER APPLY电子邮件,之后只需使用任何方法将它们连接起来:

DISTINCT

此处我使用了STRING_AGG,可以从SQL Server vNext获取。

答案 1 :(得分:2)

另一个选项(如果你想保留UDF)

Declare @EMail1 varchar(50) = 'some@email.com'
Declare @EMail2 varchar(50) = 'some@email.com'
Declare @EMail3 varchar(50) = 'someother@email.com'
Declare @EMail4 varchar(50) = 'some@email.com'

Select Stuff((Select Distinct ','+EMails From (values (@EMail1),(@EMail2),(@EMail3),(@EMail4) ) A (EMails) For XML Path('')),1,1,'')

返回

some@email.com,someother@email.com
  

作为功能

Create FUNCTION [dbo].[CombineAndCommaSeparateEmails] (@Email1 VARCHAR(250),@Email2 VARCHAR(250),@Email3 VARCHAR(250),@Email4 VARCHAR(250))

Returns varchar(250)
AS 

BEGIN
    Return (
    Select Stuff((Select Distinct ','+EMails 
                  From  (values (@EMail1)
                               ,(@EMail2)
                               ,(@EMail3)
                               ,(@EMail4) 
                         ) A (EMails) 
                   Where EMails<>''
                   For XML Path('')),1,1,'')
    )
End

所以

Select [dbo].[CombineAndCommaSeparateEmails]('some@email.com','some@email.com','someother@email.com',null)

返回

some@email.com,someother@email.com

答案 2 :(得分:1)

使用一些虚拟测试数据:

CREATE TABLE people (
    ID INT,
    Name VARCHAR(50),
    Email1 VARCHAR(50),
    Email2 VARCHAR(50),
    Email3 VARCHAR(50),
    Email4 VARCHAR(50)
)

INSERT INTO people (ID, Name, Email1, Email2, Email3, Email4) VALUES
(1, 'John Smith', 'jsmith@gmail.com', 'johns@work.com', '', 'jsmith@gmail.com'),
(2, 'Jane Doe', 'janedoe2001@gmail.com', 'janed@business.com', '', ''),
(3, 'Roger White', 'rwhite@gmail.com', 'whitey@somewhere.com', 'rwhite@gmail.com', 'rwhite@gmail.com');

我创建了一个CTE来返回所有唯一的电子邮件地址,然后使用FOR XML PATH将它们合并:

WITH uniqueEmails (ID, Name, Email) AS
(
    SELECT ID, Name, Email1 AS Email
    FROM people
    UNION
    SELECT ID, Name, Email2 AS Email
    FROM people
    UNION
    SELECT ID, Name, Email3 AS Email
    FROM people
    UNION
    SELECT ID, Name, Email4 AS Email
    FROM people
)
SELECT DISTINCT
    e.ID,
    e.Name, 
    STUFF(
            (
                SELECT ',' + e2.Email
                FROM uniqueEmails e2
                WHERE e2.ID = e.ID
                AND ISNULL(e2.Email,'') <> ''
                GROUP BY e2.Email
                ORDER BY e2.Email
                FOR XML PATH('')
            ), 1, 1, ''
         ) AS Emails
FROM uniqueEmails e
WHERE ISNULL(e.Email,'') <> ''

对于上面的测试数据,这会得到以下结果:

/-------------------------------------------------------------\
| ID |     Name    |                  Emails                  |
|----+-------------+------------------------------------------|
|  1 | John Smith  | johns@work.com,jsmith@gmail.com          |
|  2 | Jane Doe    | janed@business.com,janedoe2001@gmail.com |
|  3 | Roger White | rwhite@gmail.com,whitey@somewhere.com    |
\-------------------------------------------------------------/

答案 3 :(得分:0)

首先使用CROSS APPLY和VALUES删除重复项,然后使用XML PATH STUFF将其重新组合在一起。

DROP TABLE #TMP
CREATE TABLE #TMP (ID INT
                    ,Text1 VARCHAR(255)
                    ,Text2 VARCHAR(255)
                    ,Text3 VARCHAR(255)
                    ,Text4 VARCHAR(255)
                    )

INSERT INTO  #TMP VALUES
(1,'aaa','bbb','ccc','ddd')
,(2,'fff','ggg','fff','hhh')    --Row With Duplicate

;WITH cte_UP    --Remove Duplicates Using an unpivot CROSS APPLY with VALUES
    AS
    (
    SELECT DISTINCT
        T.ID
        ,U.Textn
    FROM
        #TMP T CROSS APPLY (VALUES (T.Text1)
                                    ,(T.Text2)
                                    ,(T.Text3)
                                    ,(T.Text4))
                                    U(Textn)
    )
--USE XML STUFF TO CONCATENATE UNIQUE VALUES
SELECT 
    ID,
    STUFF((
        SELECT ','+ cast(Textn AS NVARCHAR(255))
        FROM cte_UP b
        WHERE a.ID = b.ID
        FOR XML PATH('')
        )
,1,1,'') AS TextN
FROM cte_UP a
GROUP BY a.ID