Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在SQL中,如何透视表并获取详细信息?_Sql_Sql Server_Tsql_Pivot - Fatal编程技术网

在SQL中,如何透视表并获取详细信息?

在SQL中,如何透视表并获取详细信息?,sql,sql-server,tsql,pivot,Sql,Sql Server,Tsql,Pivot,我有以下TSQL测试数据: IF OBJECT_ID('dbo.emp') IS NOT NULL DROP TABLE dbo.emp; CREATE TABLE dbo.emp (name NVARCHAR(10), dept NVARCHAR(10)); GO INSERT INTO dbo.emp (name, dept) VALUES (N'user1', N'dept1'), (N'user2', N'dept1'), (N'user3', N'dept2'), (N'us

我有以下TSQL测试数据:

IF OBJECT_ID('dbo.emp') IS NOT NULL
    DROP TABLE dbo.emp;
CREATE TABLE dbo.emp (name NVARCHAR(10), dept NVARCHAR(10));
GO

INSERT INTO dbo.emp (name, dept)
VALUES
(N'user1', N'dept1'),
(N'user2', N'dept1'),
(N'user3', N'dept2'),
(N'user4', N'dept2'),
(N'user5', N'dept2'),
(N'user6', N'dept3');
如何透视数据并获得每行的详细信息?我想要的结果是:

+-------+-------+-------+
| dept1 | dept2 | dept3 |
+-------+-------+-------+
| user1 | user3 | user6 |
| user2 | user4 | NULL  |
| NULL  | user5 | NULL  |
+-------+-------+-------+
现在我提出了这个问题:

WITH
    cte1 AS (
                SELECT name                              dept1,
                       ROW_NUMBER() OVER (ORDER BY name) row
                FROM dbo.emp
                WHERE
                    dept = 'dept1'
            ),
    cte2 AS (
                SELECT name                              dept2,
                       ROW_NUMBER() OVER (ORDER BY name) row
                FROM dbo.emp
                WHERE
                    dept = 'dept2'
            ),
    cte3 AS (
                SELECT name                              dept3,
                       ROW_NUMBER() OVER (ORDER BY name) row
                FROM dbo.emp
                WHERE
                    dept = 'dept3'
            )
SELECT cte1.dept1,
       cte2.dept2,
       cte3.dept3
FROM cte1
     FULL OUTER JOIN cte2
         ON cte2.row = cte1.row
     FULL OUTER JOIN cte3
         ON cte3.row = cte1.row;
这给了我正确的结果。但是,当我将演示数据更改为:

IF OBJECT_ID('dbo.emp') IS NOT NULL
    DROP TABLE dbo.emp;
CREATE TABLE dbo.emp (name NVARCHAR(10), dept NVARCHAR(10));
GO

INSERT INTO dbo.emp (name, dept)
VALUES
(N'user1', N'dept1'),
(N'user2', N'dept1'),
(N'user3', N'dept2'),
(N'user4', N'dept2'),
(N'user5', N'dept2'),
(N'user6', N'dept3'),
(N'user7', N'dept3'),
(N'user8', N'dept3');
后面提到的查询给出:

+-------+-------+-------+
| dept1 | dept2 | dept3 |
+-------+-------+-------+
| user1 | user3 | user6 |
| user2 | user4 | user7 |
| NULL  | user5 | NULL  |
| NULL  | NULL  | user8 |
+-------+-------+-------+
这不是我想要的。我期待的结果是:

+-------+-------+-------+
| dept1 | dept2 | dept3 |
+-------+-------+-------+
| user1 | user3 | user6 |
| user2 | user4 | user7 |
| NULL  | user5 | user8 |
+-------+-------+-------+

注意:用户名在每列中按顺序排列。希望有人能给我指出正确的方向

如果您的部门列表是动态的,那么这只处理3列,那么我们必须使用动态SQL来处理
n
列数。。。但正如您在示例中硬编码的3,我假设是3

使用rank()但row_number也起作用;但是,边缘情况可能会产生不同的结果

我没有考虑边缘情况,比如如果你的数据中的同一个部门有重复的用户名…这些会被合并为1吗,或者您希望看到多行,或者这在数据中是不可能的

使用max和按行数分组是我们得到非空行的原因。 至于为什么。。每个行号对于部门内的每个名称都是唯一的。但是,边缘案例可能会导致问题,因为行号是基于部门中的有序用户分配的,所有类似的行将合并为一行

您不需要多个cte,我们只需按部门划分即可。 分区内名称的排序方式确保名称按字母顺序排列。然后我们按末尾的行号排序

CREATE TABLE emp53564443 (name NVARCHAR(10), dept NVARCHAR(10));

INSERT INTO emp53564443 (name, dept)
VALUES
(N'user1', N'dept1'),
(N'user2', N'dept1'),
(N'user3', N'dept2'),
(N'user4', N'dept2'),
(N'user5', N'dept2'),
(N'user6', N'dept3'),
(N'user7', N'dept3'),
(N'user8', N'dept3');

with cte as (SELECT A.*
                 , row_number() over (partition by dept order by name) RnDEPT
             FROM emp53564443 A)

SELECT max(Case when dept='dept1' then name end) dept1
     , max(case when dept='dept2' then name end) dept2
     , max(case when dept='dept3' then name end) dept3
FROM cte
GROUP BY rnDept
ORDER BY rnDept
给我们:

+---+-------+-------+-------+
|   | dept1 | dept2 | dept3 |
+---+-------+-------+-------+
| 1 | user1 | user3 | user6 |
| 2 | user2 | user4 | user7 |
| 3 | NULL  | user5 | user8 |
+---+-------+-------+-------+

如果您的部门列表是动态的,这只处理3列,那么我们必须使用动态SQL来处理
n
列数。。。但正如您在示例中硬编码的3,我假设是3

使用rank()但row_number也起作用;但是,边缘情况可能会产生不同的结果

我没有考虑边缘情况,比如如果你的数据中的同一个部门有重复的用户名…这些会被合并为1吗,或者您希望看到多行,或者这在数据中是不可能的

使用max和按行数分组是我们得到非空行的原因。 至于为什么。。每个行号对于部门内的每个名称都是唯一的。但是,边缘案例可能会导致问题,因为行号是基于部门中的有序用户分配的,所有类似的行将合并为一行

您不需要多个cte,我们只需按部门划分即可。 分区内名称的排序方式确保名称按字母顺序排列。然后我们按末尾的行号排序

CREATE TABLE emp53564443 (name NVARCHAR(10), dept NVARCHAR(10));

INSERT INTO emp53564443 (name, dept)
VALUES
(N'user1', N'dept1'),
(N'user2', N'dept1'),
(N'user3', N'dept2'),
(N'user4', N'dept2'),
(N'user5', N'dept2'),
(N'user6', N'dept3'),
(N'user7', N'dept3'),
(N'user8', N'dept3');

with cte as (SELECT A.*
                 , row_number() over (partition by dept order by name) RnDEPT
             FROM emp53564443 A)

SELECT max(Case when dept='dept1' then name end) dept1
     , max(case when dept='dept2' then name end) dept2
     , max(case when dept='dept3' then name end) dept3
FROM cte
GROUP BY rnDept
ORDER BY rnDept
给我们:

+---+-------+-------+-------+
|   | dept1 | dept2 | dept3 |
+---+-------+-------+-------+
| 1 | user1 | user3 | user6 |
| 2 | user2 | user4 | user7 |
| 3 | NULL  | user5 | user8 |
+---+-------+-------+-------+

感谢智能解决方案。感谢智能解决方案。