问题描述
我用一些数据创建了一个这样的表。
DROP TABLE IF EXISTS #EmployeeDetail
CREATE TABLE #EmployeeDetail(Name nvarchar(50),Department nvarchar(50),IsActive INT)
INSERT INTO #EmployeeDetail(Name,Department,IsActive)
VALUES ( 'John','Account',1 ),( 'Harry','Store',0),( 'Smile','HR',1);
姓名 | 部门 | IsActive |
---|---|---|
约翰 | 账户 | 1 |
哈利 | 商店 | 0 |
微笑 | 人力资源 | 1 |
然后我使用此查询在行变成列的位置进行了旋转
DECLARE
@columns NVARCHAR(MAX) = '',@sql NVARCHAR(MAX) = '';
DROP TABLE IF EXISTS #EmployeeDetail
CREATE TABLE #EmployeeDetail(Name nvarchar(50),1);
SELECT
@columns+=QUOTENAME(Department) + ','
FROM #EmployeeDetail;
SET @columns = LEFT(@columns,LEN(@columns) - 1);
DECLARE @GrandTotalCol NVARCHAR (MAX)
SELECT @GrandTotalCol = COALESCE (@GrandTotalCol + 'ISNULL ([' +
CAST (Department AS VARCHAR) +'],0) + ','ISNULL([' + CAST(Department AS VARCHAR)+ '],0) + ')
FROM #EmployeeDetail
GROUP BY Department
ORDER BY Department;
SET @GrandTotalCol = LEFT (@GrandTotalCol,LEN (@GrandTotalCol)-1);
SET @sql ='
SELECT *,(' + @GrandTotalCol + ')
AS [Grand Total] INTO #temp_MatchesTotal FROM
(
SELECT
Name,Department
FROM #EmployeeDetail
) t
PIVOT(
COUNT(Department)
FOR Department IN ('+ @columns +')
)
AS pivot_table
SELECT * FROM #temp_MatchesTotal
DROP TABLE #temp_MatchesTotal
;';
EXECUTE sp_executesql @sql;
给出如下输出:
姓名 | 帐号 | 存储 | 人力资源 | 总计 |
---|---|---|---|---|
约翰 | 0 | 1 | 0 | 1 |
哈利 | 1 | 0 | 0 | 1 |
微笑 | 0 | 0 | 1 | 1 |
现在在此之前似乎还不错,但现在我想在这样的报告中提取一个表格:
有没有办法通过查询来实现这些类型的东西?这样我就可以轻松地将提取的数据映射到报告中。这里的透视列也根据表#EmployeeDetail 中的 IsActive 列进行过滤。
解决方法
您可以获得与所需结果类似的结果。我使用 CASE
语句来转置结果:
每个部门需要两个 CASE
语句(一个用于 IsActive,另一个用于 IsNotActive)。
SELECT
Name,SUM(CASE WHEN (Department = 'Account' AND IsActive = 1) THEN 1 ELSE 0 END) AS AccountIsActive,SUM(CASE WHEN (Department = 'Account' AND IsActive = 0) THEN 1 ELSE 0 END) AS AccountIsNotActive,SUM(CASE WHEN (Department = 'Store' AND IsActive = 1) THEN 1 ELSE 0 END) AS StoreIsActive,SUM(CASE WHEN (Department = 'Store' AND IsActive = 0) THEN 1 ELSE 0 END) AS StoreIsNotActive,SUM(CASE WHEN (Department = 'HR' AND IsActive = 1) THEN 1 ELSE 0 END) AS HRIsActive,SUM(CASE WHEN (Department = 'HR' AND IsActive = 0) THEN 1 ELSE 0 END) AS HRIsNotActive,COUNT(IsActive) AS GrandTotal
FROM #EmployeeDetail
GROUP BY Name;
输出:
名称 | AccountIsActive | AccountIsNotActive | StoreIsActive | StoreIsNotActive | HRISActive | HRISNotActive | GrandTotal |
---|---|---|---|---|---|---|---|
哈利 | 0 | 0 | 0 | 1 | 0 | 0 | 1 |
约翰 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |
微笑 | 0 | 0 | 0 | 0 | 1 | 0 | 1 |
动态查询
SELECT STRING_AGG(query_piece,'')
FROM (
(SELECT 'SELECT Name,' AS query_piece)
UNION ALL
(SELECT
CONCAT('SUM(CASE WHEN Department = ''',Department,''' AND IsActive = ',IsActive,' THEN 1 ELSE 0 END) AS ','_',CASE WHEN IsActive = 1 THEN 'IsActive' ELSE 'IsNotActive' END,',')
FROM (SELECT DISTINCT Department FROM #EmployeeDetail) AS sqD
CROSS JOIN (SELECT DISTINCT IsActive FROM #EmployeeDetail) AS sqIA)
UNION ALL
(SELECT 'COUNT(IsActive) AS GrandTotal
FROM #EmployeeDetail
GROUP BY Name;')) AS dynamic_query;
动态查询输出是您请求的查询:
SELECT Name,SUM(CASE WHEN Department = 'Account' AND IsActive = 0 THEN 1 ELSE 0 END) AS Account_IsNotActive,SUM(CASE WHEN Department = 'HR' AND IsActive = 0 THEN 1 ELSE 0 END) AS HR_IsNotActive,SUM(CASE WHEN Department = 'Store' AND IsActive = 0 THEN 1 ELSE 0 END) AS Store_IsNotActive,SUM(CASE WHEN Department = 'Account' AND IsActive = 1 THEN 1 ELSE 0 END) AS Account_IsActive,SUM(CASE WHEN Department = 'HR' AND IsActive = 1 THEN 1 ELSE 0 END) AS HR_IsActive,SUM(CASE WHEN Department = 'Store' AND IsActive = 1 THEN 1 ELSE 0 END) AS Store_IsActive,COUNT(IsActive) AS GrandTotal
FROM #EmployeeDetail
GROUP BY Name;