0

我有几张桌子,如下所示

位置表

ID 职位名称
1 开发商
2 分析师
3 测试仪

员工表

ID 姓名 职位
1 约翰 1,2
2 丽莎 3
3 史密斯 1
4 NULL
5 魁梧 2,3

从上表中,生成如下透视报告的查询是什么?

ID 姓名 开发商 分析师 测试仪
1 约翰 ñ
2 丽莎 ñ ñ
3 史密斯 ñ ñ
4 ñ ñ ñ
5 魁梧 ñ

我坚持这样一个事实,我必须做一些拆分字符串并使用CASE WHEN来应用YN到枢轴。

这是我在 SQL 小提琴中的操场http://sqlfiddle.com/#!18/2ad8d/31

4

2 回答 2

0

您只需要加入Position表格即可获取职位名称

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX);

SET @cols = STUFF((SELECT DISTINCT ',' + QUOTENAME(Name)
    FROM Position
    FOR XML PATH(''), TYPE ).value('text()[1]', 'NVARCHAR(MAX)') 
        ,1,1,'');

set @query = N'
SELECT Name,' + @cols + N'
from 
(
    SELECT e.Name, p.PositionName
    FROM Employee AS e
    CROSS APPLY dbo.SplitString(Position, '','') AS ep(PositionId)
    JOIN Position AS p ON p.Id = ep.PositionId
) x
pivot 
(
    COUNT(*)
    FOR p.PositionName IN (' + @cols + N')
) p
';

exec sp_executesql @query;
于 2021-04-08T10:21:58.000 回答
0

我现在无法让 Fiddle 工作,但代码还不错,不能完全重现。请注意,您应该注意您的 @Cols 变量,以确保您的所有位置名称在现实生活中都用作列名称,但通常情况并非如此!另请注意,您的原始示例有重复的员工 ID,我给了它们唯一的值。

CREATE  table Position (
  Id int,
  Name varchar(10)
);

insert into Position values
(1, 'Developer'),
(2, 'Analyist'),
(3, 'Tester');

CREATE table Employee (
  Id int,
  Name varchar(10),
  Position varchar(MAX)
);

insert into Employee values
(1, 'John', '1,3'),
(2, 'Lisa', '3'),
(3, 'Smith', '1'),
(4, 'Willow', NULL),
(5, 'Burly', '2,3');

--This is your basic working PIVOT, we'll implement as a dynamic query once we're satisfied it works
;with cteEmp as (
    SELECT E.Id as EID, E.Name as EName, P.Name as PName
        , CASE WHEN CHARINDEX(CONVERT(nvarchar(10), P.Id)
            , CONCAT(',', E.Position, ',') ) > 0 THEN 'Y' ELSE 'N' END as HasPos 
    FROM Employee as E CROSS JOIN Position as P
)SELECT Piv.* FROM cteEmp as E PIVOT (max(HasPos) FOR PName in (Developer, Analyist, Tester)) as Piv;


--To make it dynamic, build the list of positions from a query
DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT DISTINCT ',' + QUOTENAME(Name)
    FROM Position
    FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'with cteEmp as (
    SELECT E.Id as EID, E.Name as EName, P.Name as PName
        , CASE WHEN CHARINDEX(CONVERT(nvarchar(10), P.Id)
            --, CONCAT('','', E.Position, '','') ) > 0 --Not 2008R2!
            , '','' + E.Position + '','' ) > 0  
               THEN ''Y'' ELSE ''N'' END as HasPos 
    FROM Employee as E CROSS JOIN Position as P
)SELECT Piv.* FROM cteEmp as E PIVOT (max(HasPos) 
FOR PName in (' + @cols + ') ) as Piv;'

execute(@query)

编辑:修复了动态查询中缺少的右括号。

编辑:注意:这不使用拆分功能,它利用了 ID 必须是整数并且列出的位置以可预测的方式分隔的事实。我们不需要职位 ID 列表,我们只需要知道相关职位 ID 是否在列表中。我们添加和附加逗号,这样我们就可以搜索“,1”,而不仅仅是“1”,因为“1”也会匹配“21”,但“,1”只匹配单个 ID。

于 2021-04-08T10:37:08.463 回答