Sql 使用派生值可能多次出现的多列的动态透视
我试图找到一种方法,根据两列中的值动态地透视结果集 我有一个非常基本的查询,它返回与特定作业关联的事件的信息Sql 使用派生值可能多次出现的多列的动态透视,sql,sql-server,tsql,pivot,Sql,Sql Server,Tsql,Pivot,我试图找到一种方法,根据两列中的值动态地透视结果集 我有一个非常基本的查询,它返回与特定作业关联的事件的信息 SELECT num, dat, [jobevtcls-cde] ,cde FROM jobevt WHERE (num = 3177564) ORDER BY cde 查询结果如下: +=========+============+===============+=====+ | num | dat | jobevtcls-cde | cde | +====
SELECT num, dat, [jobevtcls-cde] ,cde
FROM jobevt
WHERE (num = 3177564)
ORDER BY cde
查询结果如下:
+=========+============+===============+=====+
| num | dat | jobevtcls-cde | cde |
+=========+============+===============+=====+
| 3177564 | 2021-02-24 | SYS | 10 |
+---------+------------+---------------+-----+
| 3177564 | 2021-02-24 | SYS | 40 |
+---------+------------+---------------+-----+
| 3177564 | 2021-02-24 | SYS | 40 |
+---------+------------+---------------+-----+
| 3177564 | 2021-02-24 | SYS | 40 |
+---------+------------+---------------+-----+
| 3177564 | 2021-02-24 | SYS | 42 |
+---------+------------+---------------+-----+
| 3177564 | 2021-02-24 | SYS | 60 |
+---------+------------+---------------+-----+
| 3177564 | 2021-02-24 | SYS | 60 |
+---------+------------+---------------+-----+
| 3177564 | 2021-02-24 | SYS | 89 |
+---------+------------+---------------+-----+
| 3177564 | 2021-02-24 | SYS | 100 |
+---------+------------+---------------+-----+
| 3177564 | 2021-02-24 | SYS | 115 |
+---------+------------+---------------+-----+
| 3177564 | 2021-02-24 | GEN | 120 |
+---------+------------+---------------+-----+
| 3177564 | 2021-03-01 | GEN | 120 |
+---------+------------+---------------+-----+
| 3177564 | 2021-02-26 | GEN | 160 |
+---------+------------+---------------+-----+
| 3177564 | 2021-02-24 | SYS | 198 |
+---------+------------+---------------+-----+
| 3177564 | 2021-02-24 | GEN | 210 |
+---------+------------+---------------+-----+
| 3177564 | 2021-02-26 | GEN | 220 |
+---------+------------+---------------+-----+
| 3177564 | 2021-02-24 | GEN | 310 |
+---------+------------+---------------+-----+
| 3177564 | 2021-02-26 | GEN | 310 |
+---------+------------+---------------+-----+
| 3177564 | 2021-02-24 | SYS | 422 |
+---------+------------+---------------+-----+
我希望将此数据透视,以将cde+[jobevtcls cde]显示为列标题,并将MAX(dat)显示为行值
下面的代码首先抱怨D中的第四列没有名字,所以我很难找出那个名字。SQL抱怨的另一件事是同一代码的多个实例,例如SYS40
DECLARE @JobEventKey NVARCHAR(MAX) = ''
DECLARE @SQL NVARCHAR(MAX) = ''
SELECT @JobEventKey += QUOTENAME([jobevtcls-cde] + CAST(cde AS VARCHAR(10))) + ','
FROM jobevt
WHERE jobevt.num = '3177564'
SET @JobEventKey = LEFT(@JobEventKey, LEN(@JobEventKey) -1)
SET @SQL =
'SELECT * FROM
(SELECT
num
,dat
,cde
,[jobevtcls-cde] + CAST(cde AS VARCHAR(10))
FROM
jobevt
WHERE
(num = 3177564)
) AS D
PIVOT (
MAX(dat)
FOR cde IN (' + @JobEventKey +
')
) AS P'
EXECUTE sp_executesql @SQL
我对这类事情还比较陌生,所以任何指导都非常感谢。我想知道为什么“相当新”的人总是倾向于从更复杂的东西开始,比如动态SQL?不管怎样,您的解决方案已经接近成功,而且错误很容易修复
动态SQL的一般指导原则:分步构建解决方案,并打印构造的查询(部分),以便在其构造过程中进行验证。这允许您执行构造的查询以验证结果
错误
没有为“D”的第4列指定列名
动态SQL查询中的子查询D
缺少列名或别名。添加带有as
的别名
为“p”多次指定了列“SYS40”
为@JobEventKey
构建值的方法将生成一个类似[SYS10]、[SYS40]、[SYS40]、…
的字符串。透视结果中的pivot
列列表P
需要唯一的列名。添加一个分组依据
,以避免重复
DECLARE @JobEventKey NVARCHAR(MAX) = ''
DECLARE @SQL NVARCHAR(MAX) = ''
SELECT @JobEventKey += QUOTENAME(cls + CAST(cde AS VARCHAR(10))) + ','
FROM jobevt
WHERE jobevt.num = '3177564'
--> num=3177564 contains multiple rows for "[SYS40]"
--> the contatenations contains duplicates!
SET @JobEventKey = LEFT(@JobEventKey, LEN(@JobEventKey) -1)
SET @SQL =
'SELECT * FROM
(SELECT
num
,dat
,cde
,cls + CAST(cde AS VARCHAR(10)) --> 4th column missing a name / alias!
FROM
jobevt
WHERE
(num = 3177564)
) AS D
PIVOT (
MAX(dat)
FOR cde IN (' + @JobEventKey +
')
) AS P'
EXECUTE sp_executesql @SQL
改进版
小调整:
- 将nvarchar(最大值)替换为更合理的内容(取决于您的数据)
- 尽可能使用表别名
- 不要在整数值周围加引号(对于整型列)
- 为数据透视后的排序列添加排序依据
DECLARE @JobEventKey NVARCHAR(1000) = '';
SELECT @JobEventKey += QUOTENAME(je.cls + CONVERT(NVARCHAR(10), je.cde)) + ','
FROM jobevt je
WHERE je.num = 3177564
group by QUOTENAME(je.cls + CONVERT(NVARCHAR(10), je.cde))
order by QUOTENAME(je.cls + CONVERT(NVARCHAR(10), je.cde));
SET @JobEventKey = LEFT(@JobEventKey, LEN(@JobEventKey)-1);
-- validate keys
select @JobEventKey;
DECLARE @sql NVARCHAR(2000) =
'SELECT P.*
FROM ( SELECT je.num
,je.dat
,je.cls + CONVERT(NVARCHAR(10), cde) as clscde
FROM jobevt je
WHERE je.num = 3177564 ) AS d
PIVOT (MAX(d.dat) FOR d.clscde IN (' + @JobEventKey + ')) AS P'
-- validate sql
select @sql;
-- execute
EXECUTE sp_executesql @sql;
结果
用于复制的数据:
create table jobevt
(
num int,
dat date,
cls nvarchar(3),
cde int
);
insert into jobevt (num, dat, cls, cde) values
(3177564, '2021-02-24', 'SYS', 10),
(3177564, '2021-02-24', 'SYS', 40),
(3177564, '2021-02-24', 'SYS', 40),
(3177564, '2021-02-24', 'SYS', 40),
(3177564, '2021-02-24', 'SYS', 42),
(3177564, '2021-02-24', 'SYS', 60),
(3177564, '2021-02-24', 'SYS', 60),
(3177564, '2021-02-24', 'SYS', 89),
(3177564, '2021-02-24', 'SYS', 100),
(3177564, '2021-02-24', 'SYS', 115),
(3177564, '2021-02-24', 'GEN', 120),
(3177564, '2021-03-01', 'GEN', 120),
(3177564, '2021-02-26', 'GEN', 160),
(3177564, '2021-02-24', 'SYS', 198),
(3177564, '2021-02-24', 'GEN', 210),
(3177564, '2021-02-26', 'GEN', 220),
(3177564, '2021-02-24', 'GEN', 310),
(3177564, '2021-02-26', 'GEN', 310),
(3177564, '2021-02-24', 'SYS', 422);
结果:
num GEN120 GEN160 GEN210 GEN220 GEN310 SYS10 SYS100 SYS115 SYS198 SYS40 SYS42 SYS422 SYS60 SYS89
------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
3177564 2021-03-01 2021-02-26 2021-02-24 2021-02-26 2021-02-26 2021-02-24 2021-02-24 2021-02-24 2021-02-24 2021-02-24 2021-02-24 2021-02-24 2021-02-24 2021-02-24
我想知道为什么“相当新”的人总是倾向于从更复杂的东西开始,比如动态SQL?不管怎样,您的解决方案已经接近成功,而且错误很容易修复
动态SQL的一般指导原则:分步构建解决方案,并打印构造的查询(部分),以便在其构造过程中进行验证。这允许您执行构造的查询以验证结果
错误
没有为“D”的第4列指定列名
动态SQL查询中的子查询D
缺少列名或别名。添加带有as
的别名
为“p”多次指定了列“SYS40”
为@JobEventKey
构建值的方法将生成一个类似[SYS10]、[SYS40]、[SYS40]、…
的字符串。透视结果中的pivot
列列表P
需要唯一的列名。添加一个分组依据
,以避免重复
DECLARE @JobEventKey NVARCHAR(MAX) = ''
DECLARE @SQL NVARCHAR(MAX) = ''
SELECT @JobEventKey += QUOTENAME(cls + CAST(cde AS VARCHAR(10))) + ','
FROM jobevt
WHERE jobevt.num = '3177564'
--> num=3177564 contains multiple rows for "[SYS40]"
--> the contatenations contains duplicates!
SET @JobEventKey = LEFT(@JobEventKey, LEN(@JobEventKey) -1)
SET @SQL =
'SELECT * FROM
(SELECT
num
,dat
,cde
,cls + CAST(cde AS VARCHAR(10)) --> 4th column missing a name / alias!
FROM
jobevt
WHERE
(num = 3177564)
) AS D
PIVOT (
MAX(dat)
FOR cde IN (' + @JobEventKey +
')
) AS P'
EXECUTE sp_executesql @SQL
改进版
小调整:
- 将nvarchar(最大值)替换为更合理的内容(取决于您的数据)
- 尽可能使用表别名
- 不要在整数值周围加引号(对于整型列)
- 为数据透视后的排序列添加排序依据
DECLARE @JobEventKey NVARCHAR(1000) = '';
SELECT @JobEventKey += QUOTENAME(je.cls + CONVERT(NVARCHAR(10), je.cde)) + ','
FROM jobevt je
WHERE je.num = 3177564
group by QUOTENAME(je.cls + CONVERT(NVARCHAR(10), je.cde))
order by QUOTENAME(je.cls + CONVERT(NVARCHAR(10), je.cde));
SET @JobEventKey = LEFT(@JobEventKey, LEN(@JobEventKey)-1);
-- validate keys
select @JobEventKey;
DECLARE @sql NVARCHAR(2000) =
'SELECT P.*
FROM ( SELECT je.num
,je.dat
,je.cls + CONVERT(NVARCHAR(10), cde) as clscde
FROM jobevt je
WHERE je.num = 3177564 ) AS d
PIVOT (MAX(d.dat) FOR d.clscde IN (' + @JobEventKey + ')) AS P'
-- validate sql
select @sql;
-- execute
EXECUTE sp_executesql @sql;
结果
用于复制的数据:
create table jobevt
(
num int,
dat date,
cls nvarchar(3),
cde int
);
insert into jobevt (num, dat, cls, cde) values
(3177564, '2021-02-24', 'SYS', 10),
(3177564, '2021-02-24', 'SYS', 40),
(3177564, '2021-02-24', 'SYS', 40),
(3177564, '2021-02-24', 'SYS', 40),
(3177564, '2021-02-24', 'SYS', 42),
(3177564, '2021-02-24', 'SYS', 60),
(3177564, '2021-02-24', 'SYS', 60),
(3177564, '2021-02-24', 'SYS', 89),
(3177564, '2021-02-24', 'SYS', 100),
(3177564, '2021-02-24', 'SYS', 115),
(3177564, '2021-02-24', 'GEN', 120),
(3177564, '2021-03-01', 'GEN', 120),
(3177564, '2021-02-26', 'GEN', 160),
(3177564, '2021-02-24', 'SYS', 198),
(3177564, '2021-02-24', 'GEN', 210),
(3177564, '2021-02-26', 'GEN', 220),
(3177564, '2021-02-24', 'GEN', 310),
(3177564, '2021-02-26', 'GEN', 310),
(3177564, '2021-02-24', 'SYS', 422);
结果:
num GEN120 GEN160 GEN210 GEN220 GEN310 SYS10 SYS100 SYS115 SYS198 SYS40 SYS42 SYS422 SYS60 SYS89
------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
3177564 2021-03-01 2021-02-26 2021-02-24 2021-02-26 2021-02-26 2021-02-24 2021-02-24 2021-02-24 2021-02-24 2021-02-24 2021-02-24 2021-02-24 2021-02-24 2021-02-24
看看事情的实际情况。你只需为第一段投赞成票。顺便说一句,标量变量聚合是不确定的,而且相当危险,您最好使用
string\u agg
或for xml path
仅在第一段中就可以获得一个向上投票。顺便说一句,标量变量聚合是不确定的,而且相当危险,您最好使用string\u agg
或作为xml路径