Kin*_*hah 12 sql-server pivot t-sql sql-server-2008-r2
我有一个具有以下结构的表:
CREATE TABLE [dbo].[AUDIT_SCHEMA_VERSION](
[SCHEMA_VER_MAJOR] [int] NOT NULL,
[SCHEMA_VER_MINOR] [int] NOT NULL,
[SCHEMA_VER_SUB] [int] NOT NULL,
[SCHEMA_VER_DATE] [datetime] NOT NULL,
[SCHEMA_VER_REMARK] [varchar](250) NULL
);
Run Code Online (Sandbox Code Playgroud)
一些示例数据(似乎 sqlfiddle 有问题.. 所以放一些示例数据):
INSERT INTO [AUDIT_SCHEMA_VERSION]([SCHEMA_VER_MAJOR],[SCHEMA_VER_MINOR],[SCHEMA_VER_SUB],[SCHEMA_VER_DATE],[SCHEMA_VER_REMARK])
VALUES(1,6,13,CAST('20130405 04:41:25.000' as DATETIME),'Stored procedure build')
INSERT INTO [AUDIT_SCHEMA_VERSION]([SCHEMA_VER_MAJOR],[SCHEMA_VER_MINOR],[SCHEMA_VER_SUB],[SCHEMA_VER_DATE],[SCHEMA_VER_REMARK])
VALUES(1,6,13,CAST('20130405 04:41:25.000' as DATETIME),'Stored procedure build')
INSERT INTO [AUDIT_SCHEMA_VERSION]([SCHEMA_VER_MAJOR],[SCHEMA_VER_MINOR],[SCHEMA_VER_SUB],[SCHEMA_VER_DATE],[SCHEMA_VER_REMARK])
VALUES(1,7,13,CAST('20130405 04:41:25.000' as DATETIME),'Stored procedure build')
INSERT INTO [AUDIT_SCHEMA_VERSION]([SCHEMA_VER_MAJOR],[SCHEMA_VER_MINOR],[SCHEMA_VER_SUB],[SCHEMA_VER_DATE],[SCHEMA_VER_REMARK])
VALUES(1,10,13,CAST('20130405 04:41:25.000' as DATETIME),'Stored procedure build')
INSERT INTO [AUDIT_SCHEMA_VERSION]([SCHEMA_VER_MAJOR],[SCHEMA_VER_MINOR],[SCHEMA_VER_SUB],[SCHEMA_VER_DATE],[SCHEMA_VER_REMARK])
VALUES(1,12,13,CAST('20130405 04:41:25.000' as DATETIME),'Stored procedure build')
INSERT INTO [AUDIT_SCHEMA_VERSION]([SCHEMA_VER_MAJOR],[SCHEMA_VER_MINOR],[SCHEMA_VER_SUB],[SCHEMA_VER_DATE],[SCHEMA_VER_REMARK])
VALUES(1,12,13,CAST('20130405 04:41:25.000' as DATETIME),'Stored procedure build')
INSERT INTO [AUDIT_SCHEMA_VERSION]([SCHEMA_VER_MAJOR],[SCHEMA_VER_MINOR],[SCHEMA_VER_SUB],[SCHEMA_VER_DATE],[SCHEMA_VER_REMARK])
VALUES(1,16,13,CAST('20130405 04:41:25.000' as DATETIME),'Stored procedure build')
INSERT INTO [AUDIT_SCHEMA_VERSION]([SCHEMA_VER_MAJOR],[SCHEMA_VER_MINOR],[SCHEMA_VER_SUB],[SCHEMA_VER_DATE],[SCHEMA_VER_REMARK])
VALUES(1,16,13,CAST('20130405 04:41:25.000' as DATETIME),'Stored procedure build')
INSERT INTO [AUDIT_SCHEMA_VERSION]([SCHEMA_VER_MAJOR],[SCHEMA_VER_MINOR],[SCHEMA_VER_SUB],[SCHEMA_VER_DATE],[SCHEMA_VER_REMARK])
VALUES(1,16,13,CAST('20130405 04:41:25.000' as DATETIME),'Stored procedure build')
INSERT INTO [AUDIT_SCHEMA_VERSION]([SCHEMA_VER_MAJOR],[SCHEMA_VER_MINOR],[SCHEMA_VER_SUB],[SCHEMA_VER_DATE],[SCHEMA_VER_REMARK])
VALUES(1,16,13,CAST('20140417 18:10:44.100' as DATETIME),'Stored procedure build')
INSERT INTO [AUDIT_SCHEMA_VERSION]([SCHEMA_VER_MAJOR],[SCHEMA_VER_MINOR],[SCHEMA_VER_SUB],[SCHEMA_VER_DATE],[SCHEMA_VER_REMARK])
VALUES(2,5,0,CAST('20140417 18:14:14.157' as DATETIME),'Stored procedure build')
INSERT INTO [AUDIT_SCHEMA_VERSION]([SCHEMA_VER_MAJOR],[SCHEMA_VER_MINOR],[SCHEMA_VER_SUB],[SCHEMA_VER_DATE],[SCHEMA_VER_REMARK])
VALUES(2,6,0,CAST('20140417 18:14:23.327' as DATETIME),'Stored procedure build')
INSERT INTO [AUDIT_SCHEMA_VERSION]([SCHEMA_VER_MAJOR],[SCHEMA_VER_MINOR],[SCHEMA_VER_SUB],[SCHEMA_VER_DATE],[SCHEMA_VER_REMARK])
VALUES(2,7,0,CAST('20140417 18:14:32.270' as DATETIME),'Stored procedure build')
INSERT INTO [AUDIT_SCHEMA_VERSION]([SCHEMA_VER_MAJOR],[SCHEMA_VER_MINOR],[SCHEMA_VER_SUB],[SCHEMA_VER_DATE],[SCHEMA_VER_REMARK])
VALUES(2,8,0,CAST('20141209 09:38:40.700' as DATETIME),'Stored procedure build')
INSERT INTO [AUDIT_SCHEMA_VERSION]([SCHEMA_VER_MAJOR],[SCHEMA_VER_MINOR],[SCHEMA_VER_SUB],[SCHEMA_VER_DATE],[SCHEMA_VER_REMARK])
VALUES(2,9,0,CAST('20141209 09:43:04.237' as DATETIME),'Stored procedure build')
INSERT INTO [AUDIT_SCHEMA_VERSION]([SCHEMA_VER_MAJOR],[SCHEMA_VER_MINOR],[SCHEMA_VER_SUB],[SCHEMA_VER_DATE],[SCHEMA_VER_REMARK])
VALUES(2,10,0,CAST('20141209 09:45:19.893' as DATETIME),'Stored procedure build')
INSERT INTO [AUDIT_SCHEMA_VERSION]([SCHEMA_VER_MAJOR],[SCHEMA_VER_MINOR],[SCHEMA_VER_SUB],[SCHEMA_VER_DATE],[SCHEMA_VER_REMARK])
VALUES(2,13,0,CAST('20150323 14:54:30.847' as DATETIME),'Stored procedure build')
INSERT INTO [AUDIT_SCHEMA_VERSION]([SCHEMA_VER_MAJOR],[SCHEMA_VER_MINOR],[SCHEMA_VER_SUB],[SCHEMA_VER_DATE],[SCHEMA_VER_REMARK])
VALUES(1,10,13,CAST('20130405 04:41:25.000' as DATETIME),'Stored procedure build')
INSERT INTO [AUDIT_SCHEMA_VERSION]([SCHEMA_VER_MAJOR],[SCHEMA_VER_MINOR],[SCHEMA_VER_SUB],[SCHEMA_VER_DATE],[SCHEMA_VER_REMARK])
VALUES(1,16,14,CAST('20140417 18:11:07.977' as DATETIME),'Stored procedure build')
INSERT INTO [AUDIT_SCHEMA_VERSION]([SCHEMA_VER_MAJOR],[SCHEMA_VER_MINOR],[SCHEMA_VER_SUB],[SCHEMA_VER_DATE],[SCHEMA_VER_REMARK])
VALUES(1,16,15,CAST('20140417 18:11:13.130' as DATETIME),'Stored procedure build')
INSERT INTO [AUDIT_SCHEMA_VERSION]([SCHEMA_VER_MAJOR],[SCHEMA_VER_MINOR],[SCHEMA_VER_SUB],[SCHEMA_VER_DATE],[SCHEMA_VER_REMARK])
VALUES(2,2,0,CAST('20140417 18:12:11.200' as DATETIME),'Stored procedure build')
INSERT INTO [AUDIT_SCHEMA_VERSION]([SCHEMA_VER_MAJOR],[SCHEMA_VER_MINOR],[SCHEMA_VER_SUB],[SCHEMA_VER_DATE],[SCHEMA_VER_REMARK])
VALUES(2,3,0,CAST('20140417 18:12:33.330' as DATETIME),'Stored procedure build')
INSERT INTO [AUDIT_SCHEMA_VERSION]([SCHEMA_VER_MAJOR],[SCHEMA_VER_MINOR],[SCHEMA_VER_SUB],[SCHEMA_VER_DATE],[SCHEMA_VER_REMARK])
VALUES(2,4,0,CAST('20140417 18:12:48.803' as DATETIME),'Stored procedure build')
INSERT INTO [AUDIT_SCHEMA_VERSION]([SCHEMA_VER_MAJOR],[SCHEMA_VER_MINOR],[SCHEMA_VER_SUB],[SCHEMA_VER_DATE],[SCHEMA_VER_REMARK])
VALUES(1,13,13,CAST('20130405 04:41:25.000' as DATETIME),'Stored procedure build')
INSERT INTO [AUDIT_SCHEMA_VERSION]([SCHEMA_VER_MAJOR],[SCHEMA_VER_MINOR],[SCHEMA_VER_SUB],[SCHEMA_VER_DATE],[SCHEMA_VER_REMARK])
VALUES(1,16,13,CAST('20130405 04:41:25.000' as DATETIME),'Stored procedure build')
INSERT INTO [AUDIT_SCHEMA_VERSION]([SCHEMA_VER_MAJOR],[SCHEMA_VER_MINOR],[SCHEMA_VER_SUB],[SCHEMA_VER_DATE],[SCHEMA_VER_REMARK])
VALUES(2,11,0,CAST('20141209 09:45:58.993' as DATETIME),'Stored procedure build')
INSERT INTO [AUDIT_SCHEMA_VERSION]([SCHEMA_VER_MAJOR],[SCHEMA_VER_MINOR],[SCHEMA_VER_SUB],[SCHEMA_VER_DATE],[SCHEMA_VER_REMARK])
VALUES(2,12,0,CAST('20141209 09:46:50.070' as DATETIME),'Stored procedure build');
Run Code Online (Sandbox Code Playgroud)
这是SQLFiddle一些示例数据。
具有 T-sql 专业知识的人可以指导我如何实现最终结果吗?我知道PIVOT
(使用动态列)将是正确的方法,但无法弄清楚。
预期成绩 :
到目前为止,我有以下内容:
select row_number() over (
partition by CONVERT(varchar(10), SCHEMA_VER_DATE, 110) order by SCHEMA_VER_DATE
) as rownum
,CONVERT(varchar(10), SCHEMA_VER_DATE, 110) as UPG_DATE
,CONVERT(varchar(1), SCHEMA_VER_MAJOR) + '.' + CONVERT(varchar(2), SCHEMA_VER_MINOR) + '.' + CONVERT(varchar(2), SCHEMA_VER_SUB) as SCHEMA_VER
from audit_schema_version
where SCHEMA_VER_REMARK like 'Stored procedure build'
order by UPGRADE_DATE
Run Code Online (Sandbox Code Playgroud)
Tar*_*ryn 20
获得最终结果有点麻烦,因为SCHEMA_VER
每个日期都有多个。在我演示如何使用动态 SQL 执行此操作之前,我将首先展示如何使用静态代码执行此操作以使逻辑正确。为了获得最终结果,您可以同时使用 pivot 和 unpivot。
但首先,我会更改您的原始查询以使用以下内容:
select
row_number() over (
partition by CONVERT(varchar(10), SCHEMA_VER_DATE, 110) order by SCHEMA_VER_MAJOR, SCHEMA_VER_MINOR, SCHEMA_VER_SUB
) as minrownum
, row_number() over (
partition by CONVERT(varchar(10), SCHEMA_VER_DATE, 110) order by SCHEMA_VER_MAJOR desc, SCHEMA_VER_MINOR desc, SCHEMA_VER_SUB desc
) as maxrownum
,CONVERT(varchar(10), SCHEMA_VER_DATE, 110) as UPG_DATE
,CONVERT(varchar(1), SCHEMA_VER_MAJOR) + '.' + CONVERT(varchar(2), SCHEMA_VER_MINOR) + '.' + CONVERT(varchar(2), SCHEMA_VER_SUB) as SCHEMA_VER
from audit_schema_version
where SCHEMA_VER_REMARK like 'Stored procedure build';
Run Code Online (Sandbox Code Playgroud)
请参阅SQL Fiddle with Demo。我过去常常row_number()
得到SCHEMA_VER
每个日期的第一个和最后一个。这是必需的,因此您可以仅将这些值连接在一起以进行注释。
然后我将使用临时表来存储具有 1minrownum
和maxrownum
1的行。临时表将包含upg_date
和comment
。此注释列包含SCHEMA_VER
每个日期的一对串联字符串。
create table #srcData
(
upg_date varchar(10),
comment varchar(500)
);
Run Code Online (Sandbox Code Playgroud)
填充临时表的代码将是:
;with cte as
(
select
row_number() over (
partition by CONVERT(varchar(10), SCHEMA_VER_DATE, 110) order by SCHEMA_VER_MAJOR, SCHEMA_VER_MINOR, SCHEMA_VER_SUB
) as minrownum
, row_number() over (
partition by CONVERT(varchar(10), SCHEMA_VER_DATE, 110) order by SCHEMA_VER_MAJOR desc, SCHEMA_VER_MINOR desc, SCHEMA_VER_SUB desc
) as maxrownum
,CONVERT(varchar(10), SCHEMA_VER_DATE, 110) as UPG_DATE
,CONVERT(varchar(1), SCHEMA_VER_MAJOR) + '.' + CONVERT(varchar(2), SCHEMA_VER_MINOR) + '.' + CONVERT(varchar(2), SCHEMA_VER_SUB) as SCHEMA_VER
from audit_schema_version
where SCHEMA_VER_REMARK like 'Stored procedure build'
)
insert into #srcData
select distinct
c1.UPG_DATE,
comment
= STUFF((
SELECT ' - ' + c2.SCHEMA_VER
FROM cte c2
WHERE (c2.minrownum = 1 or c2.maxrownum = 1)
and c1.upg_date = c2.upg_date
order by c2.minrownum
FOR XML PATH(''), TYPE).value('.[1]', 'nvarchar(max)'), 1, 2, '')
from cte c1
where c1.minrownum = 1 or c1.maxrownum = 1;
Run Code Online (Sandbox Code Playgroud)
第一次通过您的数据可以让您:
| upg_date | comment |
|------------|-------------------|
| 03-23-2015 | 2.13.0 |
| 04-05-2013 | 1.6.13 - 1.16.13 |
| 04-17-2014 | 1.16.13 - 2.7.0 |
| 12-09-2014 | 2.8.0 - 2.12.0 |
Run Code Online (Sandbox Code Playgroud)
现在,您仍然需要计算一年中的每个日期以及完整的串联注释。这将是 unpivot 发挥作用的地方。您可以使用以下代码为每年创建完整评论并获取计数。
select distinct
Yr = right(s1.upg_date, 4),
cnt = count(*) over(partition by right(s1.upg_date, 4)),
fullcomment
= STUFF((
SELECT '; ' + s2.comment
FROM #srcData s2
WHERE right(s1.upg_date, 4) = right(s2.upg_date, 4)
FOR XML PATH(''), TYPE).value('.[1]', 'nvarchar(max)'), 1, 2, '')
from #srcData s1;
Run Code Online (Sandbox Code Playgroud)
请参阅SQL Fiddle with Demo。数据现在看起来像:
| Yr | cnt | fullcomment |
|------|-----|-----------------------------------|
| 2013 | 1 | 1.6.13 - 1.16.13 |
| 2014 | 2 | 1.16.13 - 2.7.0; 2.8.0 - 2.12.0 |
| 2015 | 1 | 2.13.0 |
Run Code Online (Sandbox Code Playgroud)
如您所见,您有多个需要旋转的列,因此您可以将fullcomment
和cnt
列都反旋转为多行。这可以使用 UNPIVOT 函数或 CROSS APPLY 来完成。我更喜欢在这里交叉应用,因为您需要将值连接在一起以创建新的列名:
;with cte as
(
select distinct
Yr = right(s1.upg_date, 4),
cnt = count(*) over(partition by right(s1.upg_date, 4)),
fullcomment
= STUFF((
SELECT '; ' + s2.comment
FROM #srcData s2
WHERE right(s1.upg_date, 4) = right(s2.upg_date, 4)
FOR XML PATH(''), TYPE).value('.[1]', 'nvarchar(max)'), 1, 2, '')
from #srcData s1
)
select [2015], [2015_comment], [2014], [2014_comment], [2013], [2013_comment]
from
(
select c.col, val
from cte d
cross apply
(
values
(Yr, cast(cnt as nvarchar(50))),
(Yr+'_comment', fullcomment)
) c (col, val)
) d
pivot
(
max(val)
for col in ([2015], [2015_comment], [2014], [2014_comment], [2013], [2013_comment])
) piv;
Run Code Online (Sandbox Code Playgroud)
一旦掌握了逻辑,就可以轻松地将其转换为动态 SQL。
-- get list of the columns
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT ',' + QUOTENAME(col)
from #srcData
cross apply
(
select right(upg_date, 4), right(upg_date, 4), 2 union all
select right(upg_date, 4), right(upg_date, 4)+'_comment', 1
) c (yr, col, so)
group by yr, col, so
order by yr desc, so desc
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query
= 'SELECT ' + @cols + '
from
(
select c.col, val
from
(
select distinct
Yr = right(s1.upg_date, 4),
cnt = count(*) over(partition by right(s1.upg_date, 4)),
fullcomment
= STUFF((
SELECT ''; '' + s2.comment
FROM #srcData s2
WHERE right(s1.upg_date, 4) = right(s2.upg_date, 4)
FOR XML PATH(''''), TYPE).value(''.[1]'', ''nvarchar(max)''), 1, 2, '''')
from #srcData s1
) d
cross apply
(
values
(Yr, cast(cnt as nvarchar(50))),
(Yr+''_comment'', fullcomment)
) c (col, val)
) x
pivot
(
max(val)
for col in (' + @cols + ')
) p '
exec sp_executesql @query;
Run Code Online (Sandbox Code Playgroud)
请参阅SQL Fiddle with Demo。两个版本都会给你结果:
| 2015 | 2015_comment | 2014 | 2014_comment | 2013 | 2013_comment |
|------|--------------|------|-----------------------------------|------|-------------------|
| 1 | 2.13.0 | 2 | 1.16.13 - 2.7.0; 2.8.0 - 2.12.0 | 1 | 1.6.13 - 1.16.13 |
Run Code Online (Sandbox Code Playgroud)
添加解释和小提琴:http : //sqlfiddle.com/# !6/ c92b2/5 。
查询如下:
1. 使用子查询按日期选择最小和最大版本(最小和最大应用于整数以保证例如 6 < 16)
2. 然后选择年份(稍后分组),日期(到订单)和最小 - 最大版本
SELECT LEFT(UPG_DATE, 4) AS Year
, UPG_DATE
, CONVERT(varchar(1), MIN_VER/1000000) + '.' + CONVERT(varchar(2), (MIN_VER/1000 - (MIN_VER/1000000)*1000)) + '.' + CONVERT(varchar(2), MIN_VER%1000)
+ ' - ' + CONVERT(varchar(1), MAX_VER/1000000) + '.' + CONVERT(varchar(2), (MAX_VER/1000 - (MAX_VER/1000000)*1000)) + '.' + CONVERT(varchar(2), MAX_VER%1000) AS Versions
INTO #Versions
FROM (
SELECT CONVERT(varchar(10), SCHEMA_VER_DATE, 112) as UPG_DATE
, MIN(SCHEMA_VER_MAJOR*1000000 + SCHEMA_VER_MINOR*1000 + SCHEMA_VER_SUB) AS MIN_VER
, MAX(SCHEMA_VER_MAJOR*1000000 + SCHEMA_VER_MINOR*1000 + SCHEMA_VER_SUB) AS MAX_VER
FROM audit_schema_version
WHERE SCHEMA_VER_REMARK like 'Stored procedure build'
GROUP BY CONVERT(varchar(10), SCHEMA_VER_DATE, 112)
) Versions;
Run Code Online (Sandbox Code Playgroud)
接下来,由于将重复每一列(year 和 year_COMMENT),因此选择两列来标识数据。计算日期的数量以了解升级的数量,版本按年份分组,填充以便将所有内容合并为一行。这为我们提供了将用于数据透视的最终表。
SELECT Year, Year + '_COMMENT' as Year_COMMENT
, COUNT(Year) AS Upgrades
, STUFF((SELECT ' ; ' + SUB.Versions
FROM #Versions SUB
WHERE SUB.Year = V.Year
ORDER BY UPG_DATE ASC
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(2000)')
,1,3,'') Versions
INTO #GroupedResults
FROM #Versions V
GROUP BY Year
SELECT * FROM #GroupedResults
Run Code Online (Sandbox Code Playgroud)
结果如下:
| Year | Year_COMMENT | Upgrades | Versions |
|------|--------------|----------|----------------------------------|
| 2013 | 2013_COMMENT | 1 | 1.6.13 - 1.16.13 |
| 2014 | 2014_COMMENT | 2 | 1.16.13 - 2.7.0 ; 2.8.0 - 2.12.0 |
| 2015 | 2015_COMMENT | 1 | 2.13.0 - 2.13.0 |
Run Code Online (Sandbox Code Playgroud)
接下来,用列填充变量,按照我们想要显示的顺序排列:
DECLARE @cols VARCHAR(1000),
@finalQuery VARCHAR(2000)
SELECT @cols = STUFF((SELECT ',' + QUOTENAME(YEAR) + ',' + QUOTENAME(YEAR + '_COMMENT')
FROM #GroupedResults
GROUP BY YEAR
ORDER BY YEAR DESC
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(2000)')
,1,1,'')
Run Code Online (Sandbox Code Playgroud)
最后,波纹管查询使用交叉应用,所以我们得到:
1. col 列填充了 Year 和 Year_COMMENT 值
2. value 列填充了升级次数,在对应于年份和版本值的行中,在对应于 Year_COMMENTs 的行
在两个结果列上使用枢轴为我们提供值(与版本交替的升级数)在列(与 Year_COMMENTs 交替的年份)上
set @finalQuery = N'SELECT ' + @cols + N' from
(
select col, value
from #GroupedResults
cross apply
(
SELECT CAST(Upgrades AS VARCHAR(200)), Year
UNION ALL
SELECT CAST(Versions AS VARCHAR(200)), Year_COMMENT
) c (value, col)
) x
pivot
(
Min(value)
for col in (' + @cols + N')
) p1
; '
EXEC (@finalQuery);
DROP TABLE #Versions;
DROP TABLE #GroupedResults;
Run Code Online (Sandbox Code Playgroud)
这将返回以下结果:
| 2015 | 2015_COMMENT | 2014 | 2014_COMMENT | 2013 | 2013_COMMENT |
|------|-----------------|------|----------------------------------|------|------------------|
| 1 | 2.13.0 - 2.13.0 | 2 | 1.16.13 - 2.7.0 ; 2.8.0 - 2.12.0 | 1 | 1.6.13 - 1.16.13 |
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
764 次 |
最近记录: |