如何选择所有员工并将其显示在每个部门的行中?

时间:2019-05-24 23:20:15

标签: sql sql-server pivot self-join

下面是我要在我的select语句中处理的数据的示例。

Employee ID | Department ID  |  FirstName  |  LastName  |  Role
----------------------------------------------------------------
1           |   1            |  Jack       | Skeleton   | Cashier
2           |   2            |  Rachel     | Sparrow    | Cashier
3           |   1            |  Samuel     | Kite       | Bagger
4           |   2            |  Arnold     | Herrera    | Bagger
5           |   1            |  Edwin      | Molina     | Bagger

下面是我要如何显示数据。

Dept ID| Emp ID  |  Role  |  Emp ID  |  Role  | EmpID  |  Role  |
-----------------------------------------------------------------
1      | 1       |Cashier | 3        |Bagger  | 5      |  Bagger|
2      | 2       |Cashier | 4        |Bagger  |

我尝试了数据透视,但是为同一行中的每位员工选择相同的列对我来说是个问题。

我还要指出,每个部门都有不同数量的员工。因此,某些行将显示该部门的6名员工,而其他行将显示4或9

1 个答案:

答案 0 :(得分:0)

这应该可以为您提供所需的东西。

SET NOCOUNT ON;
GO 
--================================================================
-- create some test data...

IF OBJECT_ID('tempdb..#Department', 'U') IS NOT NULL 
BEGIN DROP TABLE #Department; END;

CREATE TABLE #Department (
    DepartmentID INT NOT NULL PRIMARY KEY,
    DepartmentName VARCHAR(50) NOT NULL 
    );
INSERT #Department (DepartmentID, DepartmentName) VALUES
    (1, 'Department 1'), (2, 'Department 2');

IF OBJECT_ID('tempdb..#Employee', 'U') IS NOT NULL 
BEGIN DROP TABLE #Employee; END;

CREATE TABLE #Employee (
    EmployeeID INT NOT NULL PRIMARY KEY,
    DepartmentID INT NOT NULL,
    FirstName VARCHAR(20) NOT NULL,
    LastName VARCHAR(20) NOT NULL,
    [Role] VARCHAR(20) NOT NULL 
    );
INSERT #Employee (EmployeeID, DepartmentID, FirstName, LastName, [Role]) VALUES

    (1, 1, 'Jack', 'Skeleton', 'Cashier'),
    (2, 2, 'Rachel', 'Sparrow', 'Cashier'),
    (3, 1, 'Samuel', 'Kite', 'Bagger'),
    (4, 2, 'Arnold', 'Herrera', 'Bagger'),
    (5, 1, 'Edwin', 'Molina', 'Bagger');

--================================================================
-- begin the actual solution...

DECLARE 
    @sql NVARCHAR(MAX) = N'',
    @debug BIT = 0;    -- choose 0 the execute the dynamic sql & 1 to print it.

WITH
    cte_columns_needed AS (
        SELECT DISTINCT 
            rn = ROW_NUMBER() OVER (PARTITION BY e.DepartmentID ORDER BY e.EmployeeID)
        FROM
            #Employee e
        )    
SELECT TOP (10000)
    @sql = CONCAT(@sql, N',
    ', QUOTENAME(N'EmpID_' + x.rn), N' = MAX(CASE WHEN ern.rn = ', cn.rn, N' THEN ern.EmployeeID END),
    ', QUOTENAME(N'Role_' + x.rn), N' = MAX(CASE WHEN ern.rn = ', cn.rn, N' THEN ern.Role END)'
    )
FROM
    cte_columns_needed cn
    CROSS APPLY ( VALUES (CONVERT(NVARCHAR(10), cn.rn)) ) x (rn)
ORDER BY
    cn.rn;

SET @sql = CONCAT(N'
SELECT 
    [DeptID] = ern.DepartmentID',
    @sql, N'
FROM (
    SELECT 
        e.EmployeeID,
        e.DepartmentID,
        e.Role,
        rn = ROW_NUMBER() OVER (PARTITION BY e.DepartmentID ORDER BY e.EmployeeID)
    FROM
        #Employee e
    ) ern
GROUP BY
    ern.DepartmentID
ORDER BY
    ern.DepartmentID;'
);

IF @debug = 1
BEGIN 
    PRINT(@sql);
END;
ELSE 
BEGIN
    EXEC sys.sp_executesql @sql;
END;

注意...对于大多数人来说,这种动态代码并不完全直观。因此,请随时提出任何问题。