sql server中的列分为子列

问题描述

我用一些数据创建了一个这样的表。

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

现在在此之前似乎还不错,但现在我想在这样的报告中提取一个表格:

enter image description here

有没有办法通过查询来实现这些类型的东西?这样我就可以轻松地将提取的数据映射到报告中。这里的透视列也根据表#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;