答案 0 :(得分:0)
如果您使用SQL-Server 2016或更高版本
,则可以使用string_split如果你没有SQL-Server 2016,那么谷歌搜索一个string_split函数 - 这个网站上有很多这样的函数,而是用它来代替string_split
这是一种使用动态SQL pivot
的方法UPDATE2在值更改时使TableReport更改
这会检查TableReport是否存在,如果存在,则应该删除它。然后我在动态SQL中添加了一个SELECT INTO语句,重新创建了表。
DECLARE @Str NVARCHAR(MAX);
DECLARE @Str2 NVARCHAR(MAX);
SELECT @Str = STUFF(
(
SELECT DISTINCT
','+QUOTENAME(Namejob)
FROM tablejob FOR XML PATH('')
), 1, 1, '');
-- PRINT @Str
SET @str2 = N'select ROW_NUMBER() over(order by idemp) as ID,Name2 as Name, '+@Str+' into dbo.TableReport from (
select b.idemp,Names as Name2,Names,namejob from tablecustomer a cross apply dbo.[fn_split_string_using_multiple_delimiters](idjob,'','')
left join tableemp b on a.idemp =b.idemp
left join tablejob c on stringlist = c.idjob
) z
PIVOT
(count(names) for Namejob in ('+@Str+'
)
) as x';
IF OBJECT_ID('dbo.TableReport', 'U') IS NOT NULL
DROP TABLE dbo.TableReport;
--PRINT @Str2;
EXEC (@Str2);
非SQL-Server2016版本的更新
首先,您必须创建一个分割字符串的函数
字符串拆分器功能
CREATE FUNCTION dbo.[fn_split_string_using_multiple_delimiters]
(
@String VARCHAR(MAX), -- input string
@delimiter VARCHAR(32) -- delimiter list
)
RETURNS @Table TABLE(rowid INT IDENTITY PRIMARY KEY,
stringlist VARCHAR(MAX)
)
BEGIN
DECLARE @Xml AS XML
DECLARE @derived_string VARCHAR(MAX)
;WITH N1 (n) AS (SELECT 1 UNION ALL SELECT 1),
N2 (n) AS (SELECT 1 FROM N1 AS X, N1 AS Y),
N3 (n) AS (SELECT 1 FROM N2 AS X, N2 AS Y),
N4 (n) AS (SELECT ROW_NUMBER() OVER(ORDER BY X.n)
FROM N3 AS X, N3 AS Y)
SELECT @derived_string=STUFF((SELECT '' + (Case When
PATINDEX('%[' + @delimiter + ']%',SUBSTRING(@String,Nums.n,1)) >0
Then ',' else LTRIM(RTRIM(SUBSTRING(@String,Nums.n,1))) end)
FROM N4 Nums WHERE Nums.n<=LEN(@String) FOR XML PATH('')),1,0,'')
SET @Xml = cast(('<a>'+replace(@derived_string,
',','</a><a>')+'</a>') AS XML)
INSERT INTO @Table SELECT A.value('.', 'VARCHAR(MAX)')
as [Column] FROM @Xml.nodes('a') AS FN(a)
RETURN
END
GO
这个硬编码的SQL与2016年的string_split一样 - 它也是动态的。
带功能的带编码的SQL
select ROW_NUMBER() over(order by idemp) as ID,Name2 as Name, [A],[B],[C] from (
select b.idemp,Names as Name2,Names,namejob from tablecustomer a cross apply dbo.[fn_split_string_using_multiple_delimiters](idjob,',')
left join tableemp b on a.idemp =b.idemp
left join tablejob c on stringlist = c.idjob
)x
PIVOT
(count(names) for Namejob in ([A],[B],[C]
)
) as x
测试数据
create table dbo.tablejob (idjob int, namejob varchar(50))
insert into tablejob
values
(1,'a'),
(2,'b'),
(3,'c')
create table dbo.tablecustomer (serialno int,idcustomer varchar(50),idemp varchar(50),idjob varchar(50))
insert into tablecustomer
values
(1,'0001','00001','1,3'),
(2,'0002','00002','1'),
(3,'0003','00001','2,3')
create table dbo.tableemp (idemp varchar(50),Names varchar(50))
insert into tableemp
values
('00001','Jon'),
('00002','Az')
动态SQL
DECLARE @Str NVARCHAR(MAX);
DECLARE @Str2 NVARCHAR(MAX);
SELECT @Str = STUFF(
(
SELECT DISTINCT
','+QUOTENAME(Namejob)
FROM tablejob FOR XML PATH('')
), 1, 1, '');
-- PRINT @Str
SET @str2 = N'select ROW_NUMBER() over(order by idemp) as ID,Name2 as Name, '+@Str+' from (
select b.idemp,Names as Name2,Names,namejob from tablecustomer a cross apply string_split(idjob,'','')
left join tableemp b on a.idemp =b.idemp
left join tablejob c on value = c.idjob
) z
PIVOT
(count(names) for Namejob in ('+@Str+'
)
) as x';
--PRINT @Str2;
EXEC (@Str2);
硬编码SQL
select ROW_NUMBER() over(order by idemp) as ID,Name2 as Name, [A],[B],[C] from (
select b.idemp,Names as Name2,Names,namejob from tablecustomer a cross apply string_split(idjob,',')
left join tableemp b on a.idemp =b.idemp
left join tablejob c on value = c.idjob
)x
PIVOT
(count(names) for Namejob in ([A],[B],[C]
)
) as x
<强>结果强>