【问题标题】:How do I select all employees and display them in rows per department?如何选择所有员工并在每个部门的行中显示它们?
【发布时间】:2019-05-24 23:20:15
【问题描述】:

下面是我想在我的 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  |

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

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

【问题讨论】:

  • 如果您不知道需要多少列,那么您需要一个动态数据透视。这在表示层可能更容易实现。
  • (显然--)这是一个常见问题。在考虑发布之前,请始终在谷歌上搜索任何错误消息以及您的问题/问题/目标的许多清晰、简洁和准确的措辞,包括和不包括您的特定字符串/名称;阅读许多答案。如果您发布问题,请使用一个短语作为标题。请参阅How to Ask 和投票箭头鼠标悬停文本。 PS如果你没有写清楚你想要什么,那么你就无法搜索它&或要求它&你希望如何编程?
  • 请在代码问题中给出minimal reproducible example--剪切&粘贴&运行代码;具有期望和实际输出的示例输入(包括逐字错误消息);明确的规范和解释。我们只有一个例子,所以我们只能猜测那是什么。需求转储不是主题问题。请参阅How to Ask,点击谷歌搜索“stackexchange 作业”和投票箭头鼠标悬停文本。展示您可以做的相关部分并在您遇到困难的地方进行解释。

标签: sql sql-server pivot self-join


【解决方案1】:

这应该可以为您提供所需的内容。

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;

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

【讨论】:

  • 我很抱歉没有尽快回复您,但这成功了。我挣扎了很长时间试图找到答案。谢谢你。虽然我尝试用更大的东西来做这件事,但我确实有问题,而且我的 @sql nvarchar(max) 对于整个查询来说太小了。关于如何使变量更大的任何想法?
  • @Jovany - nvarchar(max) 数据类型最多可以容纳两个 Unicode 文本。如果你超越了这一点,那么事情就大错特错了。我怀疑您只是超出了 PRINT() 命令的 8000K 限制...您是否看到 debug = 1 或 debug = 0 的问题?
  • 我编辑了最后一段代码以打印 sql 变量,因为我想在查询实际运行之前查看并验证它。在调试到位的情况下运行它我得到多个错误,列出我所有的列名都是无效的。我应该为此问题创建一个新帖子,还是有其他方法可以与您分享我现在正在使用的代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-01-14
  • 2018-09-19
  • 1970-01-01
  • 1970-01-01
  • 2021-09-09
  • 2017-05-06
  • 1970-01-01
相关资源
最近更新 更多