27,579
社区成员
发帖
与我相关
我的任务
分享
--需求描述:
--通过工资表,查询人员共调了几次薪资,每次调整的金额是多少(列能否动态展开)
--工资表 [人员]、[薪资年月]、[工资]
DECLARE @T1 TABLE (PersonName VARCHAR(100),YearMonth int,Amount decimal(19,9))
INSERT INTO @T1
SELECT '张三','201901','6000' UNION ALL
SELECT '李四','201901','5000' UNION ALL
SELECT '张三','201902','6000' UNION ALL
SELECT '李四','201902','5000' UNION ALL
SELECT '王五','201902','7000' UNION ALL
SELECT '张三','201903','8000' UNION ALL --+2000
SELECT '李四','201903','5000' UNION ALL
SELECT '王五','201903','7500' UNION ALL --+500
SELECT '张三','201904','8500' UNION ALL --+500
SELECT '李四','201904','5000' UNION ALL
SELECT '王五','201904','7500' UNION ALL
--想要的结果
人员 初始薪资 调薪后 调薪1 调薪2 调薪3...
张三 6000 8500 2000 500
李四 5000 5000
王五 7000 7500 500
--需求描述:
--通过工资表,查询人员共调了几次薪资
--工资表 [人员]、[薪资年月]、[工资]
DECLARE @T1 TABLE (PersonName VARCHAR(100),YearMonth int,Amount decimal(19,9))
INSERT INTO @T1
SELECT '张三','201901','6000' UNION ALL
SELECT '李四','201901','5000' UNION ALL
SELECT '张三','201902','6000' UNION ALL
SELECT '李四','201902','5000' UNION ALL
SELECT '王五','201902','7000' UNION ALL
SELECT '张三','201903','8000' UNION ALL --+2000
SELECT '李四','201903','5000' UNION ALL
SELECT '王五','201903','7500' UNION ALL --+500
SELECT '张三','201904','8500' UNION ALL --+500
SELECT '李四','201904','5000' UNION ALL
SELECT '王五','201904','7500' UNION ALL
SELECT '张三','201906','9500' UNION ALL --+500
SELECT '李四','201906','5000' UNION ALL
SELECT '王五','201906','7500'
SELECT * INTO #TEMP FROM
(SELECT *,CAST('' AS VARCHAR(50)) AS T,
CAST(0 AS DECIMAL(19,9)) AS DIFF ,
PrevAmount=(select top 1 Amount from @T1 A WHERE A.PersonName=B.PersonName AND A.YearMonth<B.YearMonth order by YearMonth DESC),
FirstAmount=(select top 1 Amount from @T1 A WHERE A.PersonName=B.PersonName order by YearMonth),
LastAmount=(select top 1 Amount from @T1 A WHERE A.PersonName=B.PersonName order by YearMonth desc)
FROM @T1 B) A
--删除没有异动数据
DELETE FROM #TEMP WHERE Amount=PrevAmount
--SELECT ROW_NUMBER()OVER(PARTITION BY PersonName order by yearmonth) as No,* from #TEMP
SELECT * INTO #TE2 FROM (SELECT ROW_NUMBER()OVER(PARTITION BY PersonName order by yearmonth) as No,* from #TEMP) A
---处理调薪次数字段
UPDATE #TE2 SET T='[第' + CAST(No-1 as varchar(50)) + '调薪]',DIFF=Amount-PrevAmount
SELECT * FROM #TE2
--处理拼接SQL
DECLARE @NAME VARCHAR(MAX),@SQL VARCHAR(MAX)
SET @NAME=STUFF((SELECT DISTINCT ',' + T FROM #TE2 WHERE T<>'[第0调薪]' FOR XML PATH('')),1,1,'')
SET @sql='WITH CTE AS (SELECT PersonName,T,dIFF,FirstAmount,LastAmount From #TE2)'
SET @sql= @sql + 'SELECT * FROM CTE PIVOT(SUM(Diff) FOR T IN ('
+ @NAME + ')) AS p';
EXEC(@SQL)
我按您的思路自己重新写了遍,加工后的#TE2和你的已经一样了,为什么行转列出来的全是NULL值呢
DECLARE @name VARCHAR(100) = '',
@seq INT = 0;
--生成临时表
SELECT *,
CAST('' AS NVARCHAR(10)) T,
CAST(0 AS INT) seq,
CAST(0 AS DECIMAL(19,9)) Diff,
LAG(Amount) OVER (PARTITION BY PersonName ORDER BY YearMonth) AS PrevAmount,
FIRST_VALUE(Amount) OVER (PARTITION BY PersonName ORDER BY YearMonth RANGE UNBOUNDED PRECEDING) FirstAmount,
LAST_VALUE(Amount) OVER (PARTITION BY PersonName
ORDER BY YearMonth
RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) LastAmount
INTO #t
FROM @T1
ORDER BY PersonName,
YearMonth;
--删除掉没有调整的数据
DELETE FROM #t WHERE PrevAmount = Amount; --加上 OR PrevAmount IS NULL则不显示无调整记录的人员
--更新调整次数及差异
UPDATE #t
SET @seq = CASE WHEN @name = PersonName THEN @seq + 1 ELSE 1 END,
@name = PersonName,
Diff = Amount-PrevAmount,
T = '调' + CAST(@seq AS VARCHAR(10)),--列名
seq = @seq;
--拼出SQL,动态查询
DECLARE @maxSeq INT = 0; --最大调整次数
DECLARE @columns NVARCHAR(MAX) = ''; --列名
DECLARE @sql NVARCHAR(MAX);
SELECT @maxSeq = MAX(seq)FROM #t;
WHILE @maxSeq > 0
BEGIN
SET @columns = '[调' + CAST(@maxSeq AS VARCHAR(10)) + ']'
+ CASE WHEN @columns <> '' THEN ',' + @columns ELSE '' END;
SET @maxSeq = @maxSeq - 1;
END;
SET @sql = 'SELECT * FROM (SELECT PersonName, T,FirstAmount,LastAmount, Diff FROM #t) a PIVOT(min(Diff) FOR T IN ('
+ @columns + ')) AS p';
--执行动态SQL
EXEC(@sql);
;with t as (
select *,row_number() over(partition by personName order by yearmonth) as m from @t1
),t1 as (
select * from t where m=1
union all
select * from t a
where m>1 and Amount<>(select Amount from t where m=a.m-1 and PersonName=a.PersonName)
),t2 as (
select *,row_number() over(partition by personName order by m) as o from t1
),t3 as (
select PersonName,Amount as 初始薪资
,(select top 1 Amount from t2 where PersonName=a.PersonName order by o desc) as 调薪后
from t2 a
where o=1
),t4 as (
select PersonName,[2] as 第一次调薪,[3] as 第二次调薪,[4] as 第三次调薪 from (
select PersonName,o,调薪幅度
from t2 a
cross apply(
select a.Amount-Amount as 调薪幅度
from t2
where o=a.o-1 and PersonName=a.PersonName
) b
where o>1
) a
pivot(max(调薪幅度) for o in ([2],[3],[4])) p
)
select a.*,第一次调薪,第二次调薪,第三次调薪
from t3 a
left join t4 b on a.PersonName=b.PersonName
调整了一下cte,这个是不使用递归的,没有统计范围限制了;with t as (
select *,row_number() over(partition by personname order by yearmonth) as times from @t1
),t1 as (
select *,convert(decimal(19,9),Amount) as n from t where times=1
union all
select a.*,convert(decimal(19,9),a.Amount-b.Amount) as n
from t a,t1 b
where a.PersonName=b.PersonName and a.times=b.times+1
)
select a.PersonName,Amount as 初始薪资,调薪后,第一次调薪,第二次调薪,第三次调薪
from t a
left join (
select PersonName,[2] as 第一次调薪,[3] as 第二次调薪,[4] as 第三次调薪 from (
select PersonName,n,row_number() over(partition by personName order by times) as sn from t1 where n<>0
) a
pivot(
max(n) for sn in ([2],[3],[4])
) p
) b on a.PersonName=b.PersonName
cross apply (
select top 1 Amount as 调薪后 from t where PersonName=a.PersonName order by times desc
) c
where times=1
大概意思就这么个逻辑,至于最多调薪多少次,不好限制,cte递归最多100次,也就是说,最多100个月的数据
IF OBJECT_ID(N'TEMPDB.DBO.#T1') IS NOT NULL
DROP TABLE #T1
GO
CREATE TABLE #T1(PersonName VARCHAR(100),YearMonth int,Amount decimal(19,9))
INSERT INTO #T1
SELECT '张三','201901','6000' UNION ALL
SELECT '李四','201901','5000' UNION ALL
SELECT '张三','201902','6000' UNION ALL
SELECT '李四','201902','5000' UNION ALL
SELECT '王五','201902','7000' UNION ALL
SELECT '张三','201903','5000' UNION ALL --+2000
SELECT '李四','201903','5000' UNION ALL
SELECT '王五','201903','7500' UNION ALL --+500
SELECT '张三','201904','8500' UNION ALL --+500
SELECT '李四','201904','5000' UNION ALL
SELECT '王五','201904','7500'
GO
DECLARE @SQL VARCHAR(MAX);
WITH CTE
AS
(SELECT *,ROW_NUMBER() OVER (PARTITION BY PERSONNAME ORDER BY YEARMONTH) AS SEQ_1,
DENSE_RANK() OVER (PARTITION BY PERSONNAME ORDER BY AMOUNT) AS SEQ_2
FROM #T1),
CTE_1
AS
(SELECT *,NEXT_AMOUNT-PRE_AMOUNT AS DIFF,
ROW_NUMBER() OVER (PARTITION BY PERSONNAME ORDER BY SEQ_1) AS SEQ_3,
COUNT(1) OVER (PARTITION BY PERSONNAME) AS SEQ_4
FROM
(SELECT A.PersonName,A.SEQ_1,A.AMOUNT AS PRE_AMOUNT,B.AMOUNT AS NEXT_AMOUNT
FROM CTE A
JOIN CTE B ON A.PersonName=B.PersonName AND A.SEQ_1=B.SEQ_1-1
WHERE A.Amount<>B.Amount) AS A)
SELECT @SQL=ISNULL(@SQL+',','')+'SUM(CASE WHEN SEQ_3='+CAST(SEQ_3 AS VARCHAR)+' AND DIFF<>0 THEN DIFF ELSE 0 END) AS DIFF'+CAST(SEQ_3 AS VARCHAR)
FROM
(SELECT DISTINCT SEQ_3 FROM CTE_1) AS A
SET @SQL='WITH CTE
AS
(SELECT *,ROW_NUMBER() OVER (PARTITION BY PERSONNAME ORDER BY YEARMONTH) AS SEQ_1,
DENSE_RANK() OVER (PARTITION BY PERSONNAME ORDER BY AMOUNT) AS SEQ_2
FROM #T1),
CTE_1
AS
(SELECT *,NEXT_AMOUNT-PRE_AMOUNT AS DIFF,
ROW_NUMBER() OVER (PARTITION BY PERSONNAME ORDER BY SEQ_1) AS SEQ_3,
COUNT(1) OVER (PARTITION BY PERSONNAME) AS SEQ_4
FROM
(SELECT A.PersonName,A.SEQ_1,A.AMOUNT AS PRE_AMOUNT,B.AMOUNT AS NEXT_AMOUNT
FROM CTE A
JOIN CTE B ON A.PersonName=B.PersonName AND A.SEQ_1=B.SEQ_1-1
WHERE A.Amount<>B.Amount) AS A),
CTE_2
AS
(SELECT * FROM CTE_1
UNION ALL
SELECT PERSONNAME,1,AMOUNT,AMOUNT,0,1,1
FROM CTE A
WHERE NOT EXISTS (SELECT 1 FROM CTE WHERE SEQ_2>1 AND A.PERSONNAME=PERSONNAME)
AND SEQ_1=1)
SELECT PERSONNAME,SUM(CASE WHEN SEQ_3=1 THEN PRE_AMOUNT ELSE 0 END) AS INI_AMOUNT,
SUM(CASE WHEN SEQ_3=SEQ_4 THEN NEXT_AMOUNT ELSE 0 END) AS CUR_AMOUNT,'
+@SQL+'
FROM CTE_2 GROUP BY PERSONNAME'
EXEC(@SQL)
DECLARE @name VARCHAR(100) = '',
@seq INT = 0;
--生成临时表
SELECT *,
CAST('' AS NVARCHAR(10)) T,
CAST(0 AS INT) seq,
CAST(0 AS DECIMAL(19,9)) Diff,
(SELECT TOP 1 Amount FROM @T1 a WHERE a.PersonName=t.PersonName AND a.YearMonth<t.YearMonth ORDER BY a.YearMonth DESC) PrevAmount,
(SELECT TOP 1 a.Amount FROM @T1 a WHERE a.PersonName=t.PersonName ORDER BY a.YearMonth) FirstAmount,
(SELECT TOP 1 a.Amount FROM @T1 a WHERE a.PersonName=t.PersonName ORDER BY a.YearMonth DESC) LastAmount
INTO #t
FROM @T1 t
ORDER BY PersonName,
YearMonth;
--删除掉没有调整的数据
DELETE FROM #t WHERE PrevAmount = Amount; --加上 OR PrevAmount IS NULL则不显示无调整记录的人员,不显示时seq不减1
SELECT *,ROW_NUMBER() OVER (PARTITION BY PersonName ORDER BY YearMonth) RowNumber INTO #t2 FROM #t
--更新调整次数及差异
UPDATE #t2
SET Diff = Amount - PrevAmount,
T = '调' + CAST(RowNumber - 1 AS VARCHAR(10)), --列名
seq = RowNumber - 1;
--拼出SQL,动态查询
DECLARE @maxSeq INT = 0; --最大调整次数
DECLARE @columns NVARCHAR(MAX) = ''; --列名
DECLARE @sql NVARCHAR(MAX);
SELECT @maxSeq = MAX(seq)FROM #t2;
WHILE @maxSeq > 0
BEGIN
SET @columns = '[调' + CAST(@maxSeq AS VARCHAR(10)) + ']'
+ CASE WHEN @columns <> '' THEN ',' + @columns ELSE '' END;
SET @maxSeq = @maxSeq - 1;
END;
SET @sql = 'SELECT * FROM (SELECT PersonName, T,FirstAmount,LastAmount, Diff FROM #t2) a PIVOT(min(Diff) FOR T IN ('
+ @columns + ')) AS p';
--执行动态SQL
EXEC(@sql);
DROP TABLE #t;
DROP TABLE #t2;
没有缺失啊,都有记录的:
[quote=引用 10 楼 Hello World, 的回复:]
换掉几个新版本才有的分析函数:
DECLARE @name VARCHAR(100) = '',
@seq INT = 0;
--生成临时表
SELECT *,
CAST('' AS NVARCHAR(10)) T,
CAST(0 AS INT) seq,
CAST(0 AS DECIMAL(19,9)) Diff,
(SELECT TOP 1 Amount FROM @T1 a WHERE a.PersonName=t.PersonName AND a.YearMonth<t.YearMonth ORDER BY a.YearMonth DESC) PrevAmount,
(SELECT TOP 1 a.Amount FROM @T1 a WHERE a.PersonName=t.PersonName ORDER BY a.YearMonth) FirstAmount,
(SELECT TOP 1 a.Amount FROM @T1 a WHERE a.PersonName=t.PersonName ORDER BY a.YearMonth DESC) LastAmount
INTO #t
FROM @T1 t
ORDER BY PersonName,
YearMonth;
--删除掉没有调整的数据
DELETE FROM #t WHERE PrevAmount = Amount; --加上 OR PrevAmount IS NULL则不显示无调整记录的人员
--更新调整次数及差异
UPDATE #t
SET @seq = CASE WHEN @name = PersonName THEN @seq + 1 ELSE 0 END,
@name = PersonName,
Diff = Amount-PrevAmount,
T = '调' + CAST(@seq AS VARCHAR(10)),--列名
seq = @seq;
--拼出SQL,动态查询
DECLARE @maxSeq INT = 0; --最大调整次数
DECLARE @columns NVARCHAR(MAX) = ''; --列名
DECLARE @sql NVARCHAR(MAX);
SELECT @maxSeq = MAX(seq)FROM #t;
WHILE @maxSeq > 0
BEGIN
SET @columns = '[调' + CAST(@maxSeq AS VARCHAR(10)) + ']'
+ CASE WHEN @columns <> '' THEN ',' + @columns ELSE '' END;
SET @maxSeq = @maxSeq - 1;
END;
SET @sql = 'SELECT * FROM (SELECT PersonName, T,FirstAmount,LastAmount, Diff FROM #t) a PIVOT(min(Diff) FOR T IN ('
+ @columns + ')) AS p';
--执行动态SQL
EXEC(@sql);
换掉几个新版本才有的分析函数:DECLARE @name VARCHAR(100) = '', @seq INT = 0; --生成临时表 SELECT *, CAST('' AS NVARCHAR(10)) T, CAST(0 AS INT) seq, CAST(0 AS DECIMAL(19,9)) Diff, (SELECT TOP 1 Amount FROM @T1 a WHERE a.PersonName=t.PersonName AND a.YearMonth<t.YearMonth ORDER BY a.YearMonth DESC) PrevAmount, (SELECT TOP 1 a.Amount FROM @T1 a WHERE a.PersonName=t.PersonName ORDER BY a.YearMonth) FirstAmount, (SELECT TOP 1 a.Amount FROM @T1 a WHERE a.PersonName=t.PersonName ORDER BY a.YearMonth DESC) LastAmount INTO #t FROM @T1 t ORDER BY PersonName, YearMonth; --删除掉没有调整的数据 DELETE FROM #t WHERE PrevAmount = Amount; --加上 OR PrevAmount IS NULL则不显示无调整记录的人员 --更新调整次数及差异 UPDATE #t SET @seq = CASE WHEN @name = PersonName THEN @seq + 1 ELSE 0 END, @name = PersonName, Diff = Amount-PrevAmount, T = '调' + CAST(@seq AS VARCHAR(10)),--列名 seq = @seq; --拼出SQL,动态查询 DECLARE @maxSeq INT = 0; --最大调整次数 DECLARE @columns NVARCHAR(MAX) = ''; --列名 DECLARE @sql NVARCHAR(MAX); SELECT @maxSeq = MAX(seq)FROM #t; WHILE @maxSeq > 0 BEGIN SET @columns = '[调' + CAST(@maxSeq AS VARCHAR(10)) + ']' + CASE WHEN @columns <> '' THEN ',' + @columns ELSE '' END; SET @maxSeq = @maxSeq - 1; END; SET @sql = 'SELECT * FROM (SELECT PersonName, T,FirstAmount,LastAmount, Diff FROM #t) a PIVOT(min(Diff) FOR T IN (' + @columns + ')) AS p'; --执行动态SQL EXEC(@sql);
DECLARE @T1 TABLE (PersonName VARCHAR(100),YearMonth int,Amount decimal(19,9))
INSERT INTO @T1
SELECT '张三','201901','6000' UNION ALL
SELECT '李四','201901','5000' UNION ALL
SELECT '张三','201902','6000' UNION ALL
SELECT '李四','201902','5000' UNION ALL
SELECT '王五','201902','7000' UNION ALL
SELECT '张三','201903','8000' UNION ALL --+2000
SELECT '李四','201903','5000' UNION ALL
SELECT '王五','201903','7500' UNION ALL --+500
SELECT '张三','201904','8500' UNION ALL --+500
SELECT '张三','201905','8800' UNION ALL --+500
SELECT '张三','201906','9200' UNION ALL --+500
SELECT '张三','201907','9600' UNION ALL --+500
SELECT '张三','201908','10500' UNION ALL --+500
SELECT '张三','201909','11000' UNION ALL --+500
SELECT '张三','201910','12000' UNION ALL --+500
SELECT '张三','201911','10500' UNION ALL --+500
SELECT '张三','201912','12000' UNION ALL --+500
SELECT '李四','201904','5000' UNION ALL
SELECT '王五','201904','7500'
select *,row_number() over(partition by personName order by yearmonth) as m
into #tx
from @t1
select * into #t1 from (
select * from #tx where m=1
union all
select * from #tx a
where m>1 and Amount<>(select Amount from #tx where m=a.m-1 and PersonName=a.PersonName)
) a
select *,row_number() over(partition by personName order by m) as o into #t2 from #t1
select PersonName,Amount as 初始薪资
,(select top 1 Amount from #t2 where PersonName=a.PersonName order by o desc) as 调薪后
into #t3
from #t2 a
where o=1
declare @sql nvarchar(max)
set @sql = ' select PersonName' + (select distinct ',['+convert(varchar,o)+'] as 调薪' + convert(varchar,o-1) from #t2 where o>1 for xml path('')) + '
into #t4
from (
select PersonName,o,调薪幅度
from #t2 a
cross apply(
select a.Amount-Amount as 调薪幅度
from #t2
where o=a.o-1 and PersonName=a.PersonName
) b
where o>1
) a
pivot(max(调薪幅度) for o in (' + stuff((select distinct ',['+convert(varchar,o)+']' from #t2 where o>1 for xml path('')),1,1,'') + ')) p
select a.*' + (select ',调薪' + convert(varchar,o-1) from #t2 where o>1 group by o order by o for xml path('')) + '
from #t3 a
left join #t4 b on a.PersonName=b.PersonName
'
exec(@sql)
drop table #tx
drop table #t1
drop table #t2
drop table #t3
调薪次数按顺序排列,之前的调薪10跑到调薪2前边了DECLARE @name VARCHAR(100) = '',
@seq INT = 0;
--生成临时表
SELECT *,
CAST('' AS NVARCHAR(10)) T,
CAST(0 AS INT) seq,
CAST(0 AS DECIMAL(19,9)) Diff,
(SELECT TOP 1 Amount FROM @T1 a WHERE a.PersonName=t.PersonName AND a.YearMonth<t.YearMonth ORDER BY a.YearMonth DESC) PrevAmount,
(SELECT TOP 1 a.Amount FROM @T1 a WHERE a.PersonName=t.PersonName ORDER BY a.YearMonth) FirstAmount,
(SELECT TOP 1 a.Amount FROM @T1 a WHERE a.PersonName=t.PersonName ORDER BY a.YearMonth DESC) LastAmount
INTO #t
FROM @T1 t
ORDER BY PersonName,
YearMonth;
--删除掉没有调整的数据
DELETE FROM #t WHERE PrevAmount = Amount; --加上 OR PrevAmount IS NULL则不显示无调整记录的人员
--更新调整次数及差异
UPDATE #t
SET @seq = CASE WHEN @name = PersonName THEN @seq + 1 ELSE 0 END,
@name = PersonName,
Diff = Amount-PrevAmount,
T = '调' + CAST(@seq AS VARCHAR(10)),--列名
seq = @seq;
--拼出SQL,动态查询
DECLARE @maxSeq INT = 0; --最大调整次数
DECLARE @columns NVARCHAR(MAX) = ''; --列名
DECLARE @sql NVARCHAR(MAX);
SELECT @maxSeq = MAX(seq)FROM #t;
WHILE @maxSeq > 0
BEGIN
SET @columns = '[调' + CAST(@maxSeq AS VARCHAR(10)) + ']'
+ CASE WHEN @columns <> '' THEN ',' + @columns ELSE '' END;
SET @maxSeq = @maxSeq - 1;
END;
SET @sql = 'SELECT * FROM (SELECT PersonName, T,FirstAmount,LastAmount, Diff FROM #t) a PIVOT(min(Diff) FOR T IN ('
+ @columns + ')) AS p';
--执行动态SQL
EXEC(@sql);
select *,row_number() over(partition by personName order by yearmonth) as m
into #t
from @t1
select * into #t1 from (
select * from #t where m=1
union all
select * from #t a
where m>1 and Amount<>(select Amount from #t where m=a.m-1 and PersonName=a.PersonName)
) a
select *,row_number() over(partition by personName order by m) as o into #t2 from #t1
select PersonName,Amount as 初始薪资
,(select top 1 Amount from #t2 where PersonName=a.PersonName order by o desc) as 调薪后
into #t3
from #t2 a
where o=1
declare @sql nvarchar(max)
set @sql = ' select PersonName' + (select distinct ',['+convert(varchar,o)+'] as 调薪' + convert(varchar,o-1) from #t2 where o>1 for xml path('')) + '
into #t4
from (
select PersonName,o,调薪幅度
from #t2 a
cross apply(
select a.Amount-Amount as 调薪幅度
from #t2
where o=a.o-1 and PersonName=a.PersonName
) b
where o>1
) a
pivot(max(调薪幅度) for o in (' + stuff((select distinct ',['+convert(varchar,o)+']' from #t2 where o>1 for xml path('')),1,1,'') + ')) p
select a.*' + (select distinct ',调薪' + convert(varchar,o-1) from #t2 where o>1 for xml path('')) + '
from #t3 a
left join #t4 b on a.PersonName=b.PersonName
'
exec(@sql)
drop table #t
drop table #t1
drop table #t2
drop table #t3
那就必须用临时表,然后动态生成sql了;with t as (
select *,row_number() over(partition by personName order by yearmonth) as m from @t1
),t1 as (
select * from t where m=1
union all
select * from t a
where m>1 and Amount<>(select Amount from t where m=a.m-1 and PersonName=a.PersonName)
),t2 as (
select *,row_number() over(partition by personName order by m) as o from t1
),t3 as (
select PersonName,Amount as 初始薪资
,(select top 1 Amount from t2 where PersonName=a.PersonName order by o desc) as 调薪后
from t2 a
where o=1
),t4 as (
select PersonName,[2] as 第一次调薪,[3] as 第二次调薪,[4] as 第三次调薪 from (
select PersonName,o,调薪幅度
from t2 a
cross apply(
select a.Amount-Amount as 调薪幅度
from t2
where o=a.o-1 and PersonName=a.PersonName
) b
where o>1
) a
pivot(max(调薪幅度) for o in ([2],[3],[4])) p
)
select a.*,第一次调薪,第二次调薪,第三次调薪
from t3 a
left join t4 b on a.PersonName=b.PersonName
调整了一下cte,这个是不使用递归的,没有统计范围限制了
SELECT *,ROW_NUMBER() OVER (PARTITION BY PERSONNAME ORDER BY YEARMONTH) AS SEQ_1,
DENSE_RANK() OVER (PARTITION BY PERSONNAME ORDER BY AMOUNT) AS SEQ_2
INTO #A
FROM @T1
DECLARE @SQL VARCHAR(1000)
;WITH CTE_1
AS
(SELECT *,NEXT_AMOUNT-PRE_AMOUNT AS DIFF,
ROW_NUMBER() OVER (PARTITION BY PERSONNAME ORDER BY SEQ_1) AS SEQ_3,
COUNT(1) OVER (PARTITION BY PERSONNAME) AS SEQ_4
FROM
(SELECT A.PersonName,A.SEQ_1,A.AMOUNT AS PRE_AMOUNT,B.AMOUNT AS NEXT_AMOUNT
FROM #A A
JOIN #A B ON A.PersonName=B.PersonName AND A.SEQ_1=B.SEQ_1-1
WHERE A.Amount<>B.Amount) AS A)
SELECT @SQL=ISNULL(@SQL+',','')+'MAX(CASE WHEN SEQ_3='+CAST(SEQ_3 AS VARCHAR)+' AND DIFF<>0 THEN DIFF ELSE 0 END) AS DIFF'+CAST(SEQ_3 AS VARCHAR)
FROM
(SELECT DISTINCT SEQ_3 FROM CTE_1) AS A
SET @SQL='WITH CTE_1
AS
(SELECT *,NEXT_AMOUNT-PRE_AMOUNT AS DIFF,
ROW_NUMBER() OVER (PARTITION BY PERSONNAME ORDER BY SEQ_1) AS SEQ_3,
COUNT(1) OVER (PARTITION BY PERSONNAME) AS SEQ_4
FROM
(SELECT A.PersonName,A.SEQ_1,A.AMOUNT AS PRE_AMOUNT,B.AMOUNT AS NEXT_AMOUNT
FROM #A A
JOIN #A B ON A.PersonName=B.PersonName AND A.SEQ_1=B.SEQ_1-1
WHERE A.Amount<>B.Amount) AS A),
CTE_2
AS
(SELECT * FROM CTE_1
UNION ALL
SELECT PERSONNAME,1,AMOUNT,AMOUNT,0,1,1
FROM #A A
WHERE NOT EXISTS (SELECT 1 FROM #A WHERE SEQ_2>1 AND A.PERSONNAME=PERSONNAME)
AND SEQ_1=1)
SELECT PERSONNAME,SUM(CASE WHEN SEQ_3=1 THEN PRE_AMOUNT ELSE 0 END) AS INI_AMOUNT,
SUM(CASE WHEN SEQ_3=SEQ_4 THEN NEXT_AMOUNT ELSE 0 END) AS CUR_AMOUNT,'
+@SQL+'
FROM CTE_2 GROUP BY PERSONNAME'
EXEC(@SQL)
使用临时表和动态SQL查询
DECLARE @name VARCHAR(100) = '',
@seq INT = 0;
--生成临时表
SELECT *,
CAST('' AS NVARCHAR(10)) T,
CAST(0 AS INT) seq,
CAST(0 AS DECIMAL(19,9)) Diff,
LAG(Amount) OVER (PARTITION BY PersonName ORDER BY YearMonth) AS PrevAmount,
FIRST_VALUE(Amount) OVER (PARTITION BY PersonName ORDER BY YearMonth RANGE UNBOUNDED PRECEDING) FirstAmount,
LAST_VALUE(Amount) OVER (PARTITION BY PersonName
ORDER BY YearMonth
RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) LastAmount
INTO #t
FROM @T1
ORDER BY PersonName,
YearMonth;
--删除掉没有调整的数据
DELETE FROM #t WHERE PrevAmount = Amount; --加上 OR PrevAmount IS NULL则不显示无调整记录的人员
--更新调整次数及差异
UPDATE #t
SET @seq = CASE WHEN @name = PersonName THEN @seq + 1 ELSE 1 END,
@name = PersonName,
Diff = Amount-PrevAmount,
T = '调' + CAST(@seq AS VARCHAR(10)),--列名
seq = @seq;
--拼出SQL,动态查询
DECLARE @maxSeq INT = 0; --最大调整次数
DECLARE @columns NVARCHAR(MAX) = ''; --列名
DECLARE @sql NVARCHAR(MAX);
SELECT @maxSeq = MAX(seq)FROM #t;
WHILE @maxSeq > 0
BEGIN
SET @columns = '[调' + CAST(@maxSeq AS VARCHAR(10)) + ']'
+ CASE WHEN @columns <> '' THEN ',' + @columns ELSE '' END;
SET @maxSeq = @maxSeq - 1;
END;
SET @sql = 'SELECT * FROM (SELECT PersonName, T,FirstAmount,LastAmount, Diff FROM #t) a PIVOT(min(Diff) FOR T IN ('
+ @columns + ')) AS p';
--执行动态SQL
EXEC(@sql);
SELECT *,ROW_NUMBER() OVER (PARTITION BY PERSONNAME ORDER BY YEARMONTH) AS SEQ_1,
DENSE_RANK() OVER (PARTITION BY PERSONNAME ORDER BY AMOUNT) AS SEQ_2
INTO #A
FROM @T1
DECLARE @SQL VARCHAR(1000)
;WITH CTE_1
AS
(SELECT *,NEXT_AMOUNT-PRE_AMOUNT AS DIFF,
ROW_NUMBER() OVER (PARTITION BY PERSONNAME ORDER BY SEQ_1) AS SEQ_3,
COUNT(1) OVER (PARTITION BY PERSONNAME) AS SEQ_4
FROM
(SELECT A.PersonName,A.SEQ_1,A.AMOUNT AS PRE_AMOUNT,B.AMOUNT AS NEXT_AMOUNT
FROM #A A
JOIN #A B ON A.PersonName=B.PersonName AND A.SEQ_1=B.SEQ_1-1
WHERE A.Amount<>B.Amount) AS A)
SELECT @SQL=ISNULL(@SQL+',','')+'MAX(CASE WHEN SEQ_3='+CAST(SEQ_3 AS VARCHAR)+' AND DIFF<>0 THEN DIFF ELSE 0 END) AS DIFF'+CAST(SEQ_3 AS VARCHAR)
FROM
(SELECT DISTINCT SEQ_3 FROM CTE_1) AS A
SET @SQL='WITH CTE_1
AS
(SELECT *,NEXT_AMOUNT-PRE_AMOUNT AS DIFF,
ROW_NUMBER() OVER (PARTITION BY PERSONNAME ORDER BY SEQ_1) AS SEQ_3,
COUNT(1) OVER (PARTITION BY PERSONNAME) AS SEQ_4
FROM
(SELECT A.PersonName,A.SEQ_1,A.AMOUNT AS PRE_AMOUNT,B.AMOUNT AS NEXT_AMOUNT
FROM #A A
JOIN #A B ON A.PersonName=B.PersonName AND A.SEQ_1=B.SEQ_1-1
WHERE A.Amount<>B.Amount) AS A),
CTE_2
AS
(SELECT * FROM CTE_1
UNION ALL
SELECT PERSONNAME,1,AMOUNT,AMOUNT,0,1,1
FROM #A A
WHERE NOT EXISTS (SELECT 1 FROM #A WHERE SEQ_2>1 AND A.PERSONNAME=PERSONNAME)
AND SEQ_1=1)
SELECT PERSONNAME,SUM(CASE WHEN SEQ_3=1 THEN PRE_AMOUNT ELSE 0 END) AS INI_AMOUNT,
SUM(CASE WHEN SEQ_3=SEQ_4 THEN NEXT_AMOUNT ELSE 0 END) AS CUR_AMOUNT,'
+@SQL+'
FROM CTE_2 GROUP BY PERSONNAME'
EXEC(@SQL)