如何以特定格式转置 SQL 中的表?
Posted
技术标签:
【中文标题】如何以特定格式转置 SQL 中的表?【英文标题】:How to transpose the table in SQL in a specific format? 【发布时间】:2018-09-25 04:49:43 【问题描述】:我需要按以下格式转置 SQL 表。数据显示应先按日期分组,然后按时间分组,并显示与时间和日期对应的值。
发件人:
Datetime | Value 1 | Value 2| Value 3
------------------------------------------------
2018-01-11 00:01:00 | 1.22 | 2.22 | 34.12
2018-01-11 00:02:00 | 2.22 | 3.22 | 43.12
2018-01-11 00:03:00 | 1.22 | 2.22 | 54.12
2018-01-11 23:58:00 | 1.22 | 2.22 | 34.12
2018-01-11 23:59:00 | 1.22 | 2.22 | 34.12
到:
| 2018-01-11 | 2018-01-12 |
Time | Value 1| Value 2| Value 3| Value 1| Value 2| Value 3|
----------------------------------------------------------------
00:01:00 | 1.22 | 2.22 | 34.12 | 1.22 | 2.22 | 34.12 |
00:02:00 | 2.22 | 3.22 | 54.13 | 2.33 | 4.32 | 54.98 |
23:58:00 | 2.22 | 3.22 | 54.13 | 2.33 | 4.32 | 54.98 |
23:59:00 | 2.22 | 3.22 | 54.13 | 2.33 | 4.32 | 54.98 |
【问题讨论】:
这些列是否具有名称 datetime、value1 和 value2?您希望在列中保留多少天?任意数? 是的 @TomC 列名称是 datetime、value1、value2 和 value3。 @TomC 我需要显示 30 天,其中日期为列,时间为行 你用的是什么数据库? SQL 不适合这种情况。在您的应用程序中执行此操作。但无论如何,我们需要知道您使用的是哪种数据库产品。 “SQL”只是一种查询语言,所有关系数据库系统都使用它。请为您正在使用的数据库产品添加tagpostgresql
, oracle
, sql-server
, db2
, ...
【参考方案1】:
这可以像这样在 sqlserver 中完成:它结合了动态数据透视表和临时表的创建。可能有更快的方法,但这可行。
首先创建示例数据:
create table #t(dt datetime, v1 decimal(5,2), v2 decimal(5,2), v3 decimal(5,2))
insert #t values
('2018-01-11 00:01:00',1.22,2.22,34.12)
,('2018-01-11 00:02:00',2.22,3.22,43.12)
,('2018-01-11 00:03:00',1.22,2.22,54.12)
,('2018-01-11 23:58:00',1.22,2.22,34.12)
,('2018-01-11 23:59:00',1.22,2.22,34.12)
,('2018-01-12 00:01:00',1.55,5.55,34.15)
,('2018-01-12 00:02:00',5.55,3.55,43.15)
,('2018-01-12 00:03:00',1.55,5.55,54.15)
,('2018-01-12 23:58:00',1.55,5.55,34.15)
,('2018-01-12 23:59:00',1.55,5.55,34.15)
然后将列转置为行:
create table #t2(t varchar(5), dv varchar(13), v decimal(5,2))
insert #t2
select convert(varchar(5),convert(time,dt)) as t,
convert(varchar(10),convert(date,dt))+' ' + v as dv,
case when v='v1' then v1 when v='v2' then v2 when v='v3' then v3 end as v
from #t
cross join (values ('v1'),('v2'),('v3')) as v(v)
然后计算出列的列表(将日期和值组合成列名)
DECLARE @cols AS VARCHAR(MAX)
select @cols=STUFF((SELECT distinct ',' + QUOTENAME(dv)
FROM #t2 c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
然后根据这些列创建一个动态查询
DECLARE @query AS VARCHAR(MAX);
set @query = 'SELECT t, ' + @cols + ' from
(
select t, dv, v
from #t2
) x
pivot
(
max(v)
for dv in (' + @cols + ')
) p '
execute(@query)
结果:(列实际上是对齐的!)
t 2018-01-11 v1 2018-01-11 v2 2018-01-11 v3 2018-01-12 v1 2018-01-12 v2 2018-01-12 v3
00:01 1.22 2.22 34.12 1.55 5.55 34.15
00:02 2.22 3.22 43.12 5.55 3.55 43.15
00:03 1.22 2.22 54.12 1.55 5.55 54.15
23:58 1.22 2.22 34.12 1.55 5.55 34.15
23:59 1.22 2.22 34.12 1.55 5.55 34.15
【讨论】:
以上是关于如何以特定格式转置 SQL 中的表?的主要内容,如果未能解决你的问题,请参考以下文章
有没有一种方法可以简单地转置 SQL 中的表。此表包含 Numeric 和 Varchar 值
如何在不使用数据透视的情况下将行转换或转置为 SQL 中的列?