SQL-如何将多个项目从1行拆分为多行

时间:2019-01-16 21:18:16

标签: sql sql-server

我正在创建一个报告,该报告将告诉我有多少电子邮件分配给报告订阅,例如,名为“每月客户活动-默认设置”的报告可以具有2个电子邮件订阅,每个订阅可以具有不同的电子邮件地址,每个订阅5个电子邮件,最后,我的报告将在一列上显示10倍的报告名称,在另一列上显示10个电子邮件地址。

我正在使用下面的代码,并且大多数时候都在工作,但是在某些行上却没有进行电子邮件拆分。我正在使用SQL Management Studio 2016,并且正在连接到我的SSRS 2016数据库

Use [ReportServer]
IF OBJECT_ID('tempdb..#Temp') IS NOT NULL
drop table #Temp

select
c.Name,
-- 'two' as OtherID,
Convert(XML,[ExtensionSettings]).value('(//ParameterValue/Value[../Name="TO"])[1]','nvarchar(max)') as email
INTO #Temp
FROM 
 dbo.[Catalog] c
INNER JOIN dbo.[Subscriptions] S ON c.ItemID = S.Report_OID
INNER JOIN dbo.ReportSchedule R ON S.SubscriptionID = R.SubscriptionID
INNER JOIN msdb.dbo.sysjobs J ON Convert(nvarchar(128),R.ScheduleID) = J.name
INNER JOIN msdb.dbo.sysjobschedules JS ON J.job_id = JS.job_id

;
WITH tmp(/*SomeID, OtherID,*/ Name, email,string) AS
(
    SELECT
        Name,
        --OtherID,
        LEFT(email, CHARINDEX(';', email + ';') - 1),
        STUFF(email, 1, CHARINDEX(';', email + ';'), '')
    FROM  #Temp

    UNION all

    SELECT
        Name,
        --OtherID,
        LEFT(email, CHARINDEX(';', email + ';') - 1),
        STUFF(email, 1, CHARINDEX(';', email + ';'), '')
    FROM tmp
    WHERE
        email != email
      and email is not NULL
)


select * from #Temp
order by email

所需的结果将是: https://imggmi.com/full/2019/1/17/a528cf472a96f5d2eff2759413b79814-full.png.html

我得到的结果:

https://imggmi.com/full/2019/1/17/4ae835b3a877ad015af10372cf7f82e9-full.png.html

正如您在图片上看到的,正在对某些行进行拆分电子邮件,但其他一些行仍在一起显示电子邮件

下面是一个示例测试:

IF OBJECT_ID('tempdb..#Temp') IS NOT NULL drop table #Temp
CREATE TABLE #Temp
(Name varchar (50) , LastStatus varchar (max) , IBOAccount varchar (10) , Email varchar (max))
GO
INSERT INTO #Temp
Select 'Report A','Email sent to Email1@email.com','47213','Email1@email.com' UNION ALL
Select 'Report A','Email sent to Email100@email.com','13983','Email100@email.com' UNION ALL
Select 'Report A','Email sent to Email101@email.com','437707','Email101@email.com' UNION ALL
Select 'Report B','Email sent to Email103@email.com','NULL','Email103@email.com' UNION ALL
Select 'Report C','Email sent to Email110@email.com','NULL','Email110@email.com' UNION ALL
Select 'Report C','Email sent to Email128@email.com','NULL','Email128@email.com' UNION ALL
Select 'Report C','Email sent to Email2@email.com;Email3@email.com','170891','Email2@email.com;Email3@email.com' UNION ALL
Select 'Report D','Done: 1 processed of 1 total; 0 errors.','NULL','Email200@email.com;Email5000@email.com;Email1000@email.com;Email_001@email.com'
GO

1 个答案:

答案 0 :(得分:1)

在这里,我根据您提供的数据进行了更改

IF OBJECT_ID('tempdb..#Temp') IS NOT NULL drop table #Temp
CREATE TABLE #Temp
(Name varchar (50) , LastStatus varchar (max) , IBOAccount varchar (10) , Email varchar (max))
GO
INSERT INTO #Temp
Select 'Report A','Email sent to Email1@email.com','47213','Email1@email.com' UNION ALL
Select 'Report A','Email sent to Email100@email.com','13983','Email100@email.com' UNION ALL
Select 'Report A','Email sent to Email101@email.com','437707','Email101@email.com' UNION ALL
Select 'Report B','Email sent to Email103@email.com','NULL','Email103@email.com' UNION ALL
Select 'Report C','Email sent to Email110@email.com','NULL','Email110@email.com' UNION ALL
Select 'Report C','Email sent to Email128@email.com','NULL','Email128@email.com' UNION ALL
Select 'Report C','Email sent to Email2@email.com;Email3@email.com','170891','Email2@email.com;Email3@email.com' UNION ALL
Select 'Report D','Done: 1 processed of 1 total; 0 errors.','NULL','Email200@email.com;Email5000@email.com;Email1000@email.com;Email_001@email.com'
GO;

declare  @result table (Name  nvarchar(max), email  varchar(MAX) )
while (select count(*) from #Temp)>0 
 begin
 declare @email varchar(max) = (select top 1 email from #temp)
 declare @Name varchar(max) = (select top 1 Name from #Temp)
 delete top (1) from #Temp where Name = @Name;
  IF RIGHT(@email, 1) <> ';'
    SELECT @email = @email + ';'

    DECLARE @Pos    BIGINT,
            @OldPos BIGINT
    SELECT  @Pos    = 1,
            @OldPos = 1

    WHILE   @Pos < LEN(@email)
        BEGIN
            SELECT  @Pos = CHARINDEX(';', @email, @OldPos)
            INSERT INTO @result (name , email)
            SELECT @Name, LTRIM(RTRIM(SUBSTRING(@email, @OldPos, @Pos - @OldPos))) email

            SELECT  @OldPos = @Pos + 1
        END

 end 

select * from @result

结果:

Name    email
Report A    Email1@email.com
Report A    Email100@email.com
Report A    Email101@email.com
Report B    Email103@email.com
Report C    Email110@email.com
Report C    Email128@email.com
Report C    Email2@email.com
Report C    Email3@email.com
Report D    Email200@email.com
Report D    Email5000@email.com
Report D    Email1000@email.com
Report D    Email_001@email.com