关于sql 表 转置 相关的请教!

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于sql 表 转置 相关的请教!相关的知识,希望对你有一定的参考价值。

表aa(id,日期,产量)

id 日期 产量
1 110101 100
2 110102 120
3 110103 50
4 110201 200
5 110202 150
6 110203 110
7 110301 120
8 110302 125
9 110303 144
10 110401 85
11 110402 40
12 110403 97
13 110501 100
14 110502 150
15 110503 124
16 110601 97
17 110602 65
18 110603 77
19 110701 87
20 110702 65
21 110703 150
: : :
: : :
id 自动增长 日期组成格式为 月+日+加单位号 如110101为 11月份01号01组
请问高手如何实现
将表查询结果为

产量1101 产量1102 产量1103 产量1104 产量1105 产量1106 产量1107 …
100 200 120 85 100 97 87 …
120 150 125 40 150 65 65 …
50 110 144 97 124 77 150 …

分别查询 各单位(从01到03排)各天的产量,横向看?

我这个三脚猫真没折了!

参考技术A 方案一:
select cc.组,max(cc.产量1101)as 产量1101,max(cc.产量1102)as 产量1102 ,max(cc.产量1103)as 产量1103,max(cc.产量1104) as 产量1104 from
(select
right(rtrim(bb.日期),2)as 组,
max(case a when '1101' then 产量 else '' end)as 产量1101,
max(case a when '1102' then 产量 else '' end)as 产量1102,
max(case a when '1103' then 产量 else '' end)as 产量1103,
max(case a when '1105' then 产量 else '' end)as 产量1104
from
(select 日期,left(日期,4)as a,产量 from dbo.aa)bb
group by
bb.日期)cc
group by cc.组

不知是不是你想要的结果,希望能够帮助你。

方案二:
select left(日期,4) as Riqi,
max(case right(rtrim(日期),2) when '01' then 产量 else 0 end)as No01,
max(case right(rtrim(日期),2) when '02' then 产量 else 0 end)as NO02,
max(case right(rtrim(日期),2) when '03' then 产量 else 0 end)as NO03
FROM dbo.aa group by left(日期,4)

你觉得这样显示行吗?
参考技术B 看这个http://apps.hi.baidu.com/share/detail/48332847
不过你的数据id应该不是固定的只有多少吧,劝你还是用临时表或者存储过程自己处理一下。
参考技术C 自己在百度里面查 “sql 行列转换”本回答被提问者采纳

t-sql 将列转置为行

【中文标题】t-sql 将列转置为行【英文标题】:t-sql transpose column into row 【发布时间】:2021-02-15 13:26:00 【问题描述】:

我这里有 3 张桌子:

Property 表。 PropertyAudit - 捕获在“属性”表中所做的一项或多项更改。 PStatus - 这是 StautsID 列的查找表。

这是我目前所拥有的。

这是表格脚本和示例数据:

CREATE TABLE Property 
(
     PropertyID INTEGER NOT NULL PRIMARY KEY
    ,StatusID INTEGER NOT NULL
    ,Country VARCHAR(11) NOT NULL
    ,Town VARCHAR(10) NOT NULL
    ,LastChangedBy VARCHAR(20) NOT NULL
    ,LastChanged VARCHAR(23) NOT NULL
);

INSERT INTO Property (
    PropertyID
    ,StatusID
    ,Country
    ,Town
    ,LastChangedBy
    ,LastChanged
    )
VALUES (
    73555
    ,1
    ,'NoMansLand'
    ,'BEEREN'
    ,'Agent009'
    ,'2020-10-15 12:41:14.280'
    );

INSERT INTO Property (
    PropertyID
    ,StatusID
    ,Country
    ,Town
    ,LastChangedBy
    ,LastChanged
    )
VALUES (
    72896
    ,6
    ,'Neverlands'
    ,'RIDDERK'
    ,'Agent007'
    ,'2020-08-10 08:41:22.447'
    );
    
CREATE TABLE PropertyAudit 
(
    AID INTEGER NOT NULL PRIMARY KEY
    ,PropertyID INTEGER NOT NULL
    ,StatusID INTEGER NOT NULL
    ,LastChangedBy VARCHAR(20) NOT NULL
    ,LastChanged VARCHAR(23) NOT NULL
)

INSERT INTO PropertyAudit (
    AID
    ,PropertyID
    ,StatusID
    ,LastChangedBy
    ,LastChanged
    )
VALUES (
    12340
    ,73555
    ,7
    ,'Agent009'
    ,'2020-10-15 12:41:14.280'
    );

INSERT INTO PropertyAudit (
    AID
    ,PropertyID
    ,StatusID
    ,LastChangedBy
    ,LastChanged
    )
VALUES (
    12341
    ,73555
    ,6
    ,'Agent007'
    ,'2020-08-24 08:10:53.223'
    );

INSERT INTO PropertyAudit (
    AID
    ,PropertyID
    ,StatusID
    ,LastChangedBy
    ,LastChanged
    )
VALUES (
    12342
    ,73555
    ,5
    ,'Agent009'
    ,'2020-02-13 14:38:10.913'
    );

INSERT INTO PropertyAudit (
    AID
    ,PropertyID
    ,StatusID
    ,LastChangedBy
    ,LastChanged
    )
VALUES (
    12343
    ,73555
    ,3
    ,'Agent009'
    ,'2020-02-13 14:33:25.967'
    );

INSERT INTO PropertyAudit (
    AID
    ,PropertyID
    ,StatusID
    ,LastChangedBy
    ,LastChanged
    )
VALUES (
    12344
    ,73555
    ,2
    ,'Agent009'
    ,'2020-02-10 13:37:57.527'
    );

CREATE TABLE PStatus 
(
     ID INTEGER NOT NULL PRIMARY KEY
    ,StatusName VARCHAR(20) NOT NULL
    ,LastChangedBy VARCHAR(20) NOT NULL
    ,LastChanged VARCHAR(23) NOT NULL
);

INSERT INTO PStatus (
    ID
    ,StatusName
    ,LastChangedBy
    ,LastChanged
    )
VALUES (
    1
    ,'REJECTED'
    ,'dbo'
    ,'2013-05-28 17:02:42.977'
    );

INSERT INTO PStatus (
    ID
    ,StatusName
    ,LastChangedBy
    ,LastChanged
    )
VALUES (
    2
    ,'NEW Contract'
    ,'dbo'
    ,'2013-05-28 17:02:42.977'
    );

INSERT INTO PStatus (
    ID
    ,StatusName
    ,LastChangedBy
    ,LastChanged
    )
VALUES (
    3
    ,'ACTIVE Contract'
    ,'dbo'
    ,'2013-10-15 12:41:14.280'
    );

INSERT INTO PStatus (
    ID
    ,StatusName
    ,LastChangedBy
    ,LastChanged
    )
VALUES (
    4
    ,'MONITOR'
    ,'dbo'
    ,'2013-10-15 12:41:14.280'
    );

INSERT INTO PStatus (
    ID
    ,StatusName
    ,LastChangedBy
    ,LastChanged
    )
VALUES (
    5
    ,'DEAL'
    ,'dbo'
    ,'2013-10-15 12:41:14.280'
    );

INSERT INTO PStatus (
    ID
    ,StatusName
    ,LastChangedBy
    ,LastChanged
    )
VALUES (
    6
    ,'DEALT'
    ,'dbo'
    ,'2013-10-15 12:41:14.280'
    );

INSERT INTO PStatus (
    ID
    ,StatusName
    ,LastChangedBy
    ,LastChanged
    )
VALUES (
    7
    ,'COMPLETED'
    ,'dbo'
    ,'2013-10-15 12:41:14.280'
    );

INSERT INTO PStatus (
    ID
    ,StatusName
    ,LastChangedBy
    ,LastChanged
    )
VALUES (
    8
    ,'ABORTED'
    ,'dbo'
    ,'2013-10-15 12:41:14.280'
    );

这就是我想要实现的目标。

最终输出:

+---------+---------------+----------------+-----------+-------------------------+
| PRD Ref | Latest_Status | Opening_Status | ChangedBy |        ChangedOn        |
+---------+---------------+----------------+-----------+-------------------------+
|   73555 | COMPLETED     | NEW CONTRACT   | Agent009  | 2020-10-15 12:41:14.280 |
+---------+---------------+----------------+-----------+-------------------------+

这是我尝试过的。

如何引入 2 列“Lastest_Status”和“Opening_Status”并从 Status 列复制值。

SELECT prop.[PropertyID] AS "PRD Ref"
    ,(
        SELECT [StatusName]
        FROM [PStatus]
        WHERE pa.StatusID = [ID]
        ) AS "Status"
    ,pa.[LastChangedBy] AS "ChangedBy"
    ,pa.[LastChanged] AS "ChangedOn"
FROM [PropertyAudit] pa
INNER JOIN [Property] prop ON pa.PropertyID = prop.PropertyID
WHERE pa.PropertyID = 73555
ORDER BY pa.PropertyID DESC
+---------+-----------------+-----------+-------------------------+
| PRD Ref |     Status      | ChangedBy |        ChangedOn        |
+---------+-----------------+-----------+-------------------------+
|   73555 | COMPLETED       | Agent009  | 2020-10-15 12:41:14.280 |
|   73555 | DEALT           | Agent007  | 2020-08-24 08:10:53.223 |
|   73555 | DEAL            | Agent009  | 2020-02-13 14:38:10.913 |
|   73555 | ACTIVE Contract | Agent009  | 2020-02-13 14:33:25.967 |
|   73555 | NEW Contract    | Agent009  | 2020-02-10 13:37:57.527 |
+---------+-----------------+-----------+-------------------------+

非常感谢。

【问题讨论】:

【参考方案1】:

这是使用窗口函数和条件聚合的一种方法:

select p.propertyid, 
    max(case when pa.rn_desc = 1 then s.statusname end) last_status,
    max(case when pa.rn_asc  = 1 then s.statusname end) opening_status,
    p.lastchangedby,
    p.lastchanged
from property p
inner join (
    select pa.*, 
        row_number() over(partition by propertyid order by lastchanged) rn_asc,
        row_number() over(partition by propertyid order by lastchanged desc) rn_desc
    from propertyaudit pa
) pa on pa.propertyid = p.propertyid
inner join pstatus s on s.id = pa.statusid
where 1 in (rn_asc, rn_desc)
group by p.propertyid, p.lastchangedby, p.lastchanged

请注意,您实际上并不需要表 property 来获得您想要的结果。我们可以进一步挖掘审计表,如下所示:

select pa.propertyid, 
    max(case when pa.rn_desc = 1 then s.statusname     end) last_status,
    max(case when pa.rn_asc  = 1 then s.statusname     end) opening_status,
    max(case when pa.rn_desc = 1 then pa.lastchangedby end) lastchangedby,
    max(case when pa.rn_desc = 1 then pa.lastchanged   end) lastchanged
from (
    select pa.*, 
        row_number() over(partition by propertyid order by lastchanged) rn_asc,
        row_number() over(partition by propertyid order by lastchanged desc) rn_desc
    from propertyaudit pa
) pa
inner join pstatus s on s.id = pa.statusid
where 1 in (rn_asc, rn_desc)
group by pa.propertyid

Demo on DB Fiddle - 两个查询都产生:

物业编号 |最后状态 |开放状态 |最后更改者 |最后更改 ---------: | :------------ | :------------- | :------------ | :------------------------ 73555 |已完成 |新合同 |代理009 | 2020-10-15 12:41:14.280

【讨论】:

太棒了,感谢您的快速回复。我使用了第一种方法,因为我将从属性中提取其他列。向你致敬.... 快速提问。我在哪里可以添加索引列以按顺序排列。如果这是有道理的。我试图在开头添加以下行,但它开始中断。 ,ROW_NUMBER() OVER(PARTITION BY PropertyID ORDER BY statusname DESC) AS "INDEX" 如果可能的话。

以上是关于关于sql 表 转置 相关的请教!的主要内容,如果未能解决你的问题,请参考以下文章

关于稀疏矩阵三元组的转置

MS SQL 转置类似于 Excel 转置(动态 SQL)

SQL for MS ACCESS 链接表转置行和列

SQL Server 转置数据 - 可能进行数据透视?

一道SQL面试题——表行列数据转换(表转置)

将 SQL 行数据转置为列