如何在PostgreSQL中将行转换为列?
我有两个数据库表,如下所示如何在PostgreSQL中将行转换为列?,sql,postgresql,sql-order-by,jooq,Sql,Postgresql,Sql Order By,Jooq,我有两个数据库表,如下所示 site id | name 1 Site One 2 Site Two 3 Site Three asset_quantities id | site_id | asset_type | quantity 1 1 1 10 2 1 2 15 3
site
id | name
1 Site One
2 Site Two
3 Site Three
asset_quantities
id | site_id | asset_type | quantity
1 1 1 10
2 1 2 15
3 1 3 25
4 2 1 11
5 2 2 16
6 2 3 7
7 3 1 12
8 3 2 15
9 3 3 16
我想编写一个SQL查询,根据给定资产类型的“数量”列对结果进行排序
例如,我想根据所有站点中资产类型1的数量对递减结果进行排序。
对于这样的场景,我将如何构建SQL查询
下面是我想要的示例结果,如果我想要所有站点中资产类型1数量的降序结果
site_id | asset_type_1_qty | asset_type_2_qty | asset_type_3_qty
3 12 15 16
2 11 16 7
1 10 15 25
这是一个示例,可以在sqlserver中执行您想要的操作。你应该能够适应深造 我有两个版本,一个是硬编码排序,第二个是使用参数来决定排序依据 首先在临时表变量中创建数据
declare @s table(id int, site_id int, asset_type int, quantity int)
insert @s values (1,1,1,10)
,(2,1,2,15)
,(3,1,3,25)
,(4,2,1,11)
,(5,2,2,16)
,(6,2,3,7)
,(7,3,1,12)
,(8,3,2,15)
,(9,3,3,16)
具有固定列排序的第一个版本
select site_id,
max(case when asset_type=1 then quantity else 0 end) as q1,
max(case when asset_type=2 then quantity else 0 end) as q2,
max(case when asset_type=3 then quantity else 0 end) as q3
from @s
group by site_id
order by 2 desc
declare @assetsort int;
set @assetsort=3
select * from (
select site_id,
max(case when asset_type=1 then quantity else 0 end) as q1,
max(case when asset_type=2 then quantity else 0 end) as q2,
max(case when asset_type=3 then quantity else 0 end) as q3
from @s
group by site_id
) q
order by
case @assetsort when 1 then q1 when 2 then q2 when 3 then q3 end desc
具有参数列排序的第二个版本
select site_id,
max(case when asset_type=1 then quantity else 0 end) as q1,
max(case when asset_type=2 then quantity else 0 end) as q2,
max(case when asset_type=3 then quantity else 0 end) as q3
from @s
group by site_id
order by 2 desc
declare @assetsort int;
set @assetsort=3
select * from (
select site_id,
max(case when asset_type=1 then quantity else 0 end) as q1,
max(case when asset_type=2 then quantity else 0 end) as q2,
max(case when asset_type=3 then quantity else 0 end) as q3
from @s
group by site_id
) q
order by
case @assetsort when 1 then q1 when 2 then q2 when 3 then q3 end desc
这是一个示例,可以在sqlserver中执行您想要的操作。你应该能够适应深造 我有两个版本,一个是硬编码排序,第二个是使用参数来决定排序依据 首先在临时表变量中创建数据
declare @s table(id int, site_id int, asset_type int, quantity int)
insert @s values (1,1,1,10)
,(2,1,2,15)
,(3,1,3,25)
,(4,2,1,11)
,(5,2,2,16)
,(6,2,3,7)
,(7,3,1,12)
,(8,3,2,15)
,(9,3,3,16)
具有固定列排序的第一个版本
select site_id,
max(case when asset_type=1 then quantity else 0 end) as q1,
max(case when asset_type=2 then quantity else 0 end) as q2,
max(case when asset_type=3 then quantity else 0 end) as q3
from @s
group by site_id
order by 2 desc
declare @assetsort int;
set @assetsort=3
select * from (
select site_id,
max(case when asset_type=1 then quantity else 0 end) as q1,
max(case when asset_type=2 then quantity else 0 end) as q2,
max(case when asset_type=3 then quantity else 0 end) as q3
from @s
group by site_id
) q
order by
case @assetsort when 1 then q1 when 2 then q2 when 3 then q3 end desc
具有参数列排序的第二个版本
select site_id,
max(case when asset_type=1 then quantity else 0 end) as q1,
max(case when asset_type=2 then quantity else 0 end) as q2,
max(case when asset_type=3 then quantity else 0 end) as q3
from @s
group by site_id
order by 2 desc
declare @assetsort int;
set @assetsort=3
select * from (
select site_id,
max(case when asset_type=1 then quantity else 0 end) as q1,
max(case when asset_type=2 then quantity else 0 end) as q2,
max(case when asset_type=3 then quantity else 0 end) as q3
from @s
group by site_id
) q
order by
case @assetsort when 1 then q1 when 2 then q2 when 3 then q3 end desc
好的,这很容易实现,只需使用
自连接
,如下所示:
select
s1.site_id,
s1.quantity as asset_type_1_qty,
s2.quantity as asset_type_2_qty,
s3.quantity as asset_type_3_qty
from
asset_quantities s1
join
asset_quantities s2 on s1.site_id=s2.site_id and s1.asset_type=1 and s2.asset_type=2
join
asset_quantities s3 on s1.site_id=s3.site_id and s3.asset_type=3
order by
s1.quantity desc
postgres=# select * from asset_quantities;
id | site_id | asset_type | quantity
----+---------+------------+----------
1 | 1 | 1 | 10
2 | 1 | 2 | 15
3 | 1 | 3 | 25
4 | 2 | 1 | 11
5 | 2 | 2 | 16
6 | 2 | 3 | 7
7 | 3 | 1 | 12
8 | 3 | 2 | 15
9 | 3 | 3 | 16
(9 rows)
postgres=# select * from crosstab(
'select
site_id,
asset_type,
quantity
from
asset_quantities order by site_id,asset_type'
) as result(site_id int,asset_type_1_qty int,asset_type_2_qty int,asset_type_3_qty int);
site_id | asset_type_1_qty | asset_type_2_qty | asset_type_3_qty
---------+------------------+------------------+------------------
1 | 10 | 15 | 25
2 | 11 | 16 | 7
3 | 12 | 15 | 16
(3 rows)
好的,有一个名为交叉表的函数,它可以将行转换为列,我认为它将完全满足您的需要,如下所示:
select
s1.site_id,
s1.quantity as asset_type_1_qty,
s2.quantity as asset_type_2_qty,
s3.quantity as asset_type_3_qty
from
asset_quantities s1
join
asset_quantities s2 on s1.site_id=s2.site_id and s1.asset_type=1 and s2.asset_type=2
join
asset_quantities s3 on s1.site_id=s3.site_id and s3.asset_type=3
order by
s1.quantity desc
postgres=# select * from asset_quantities;
id | site_id | asset_type | quantity
----+---------+------------+----------
1 | 1 | 1 | 10
2 | 1 | 2 | 15
3 | 1 | 3 | 25
4 | 2 | 1 | 11
5 | 2 | 2 | 16
6 | 2 | 3 | 7
7 | 3 | 1 | 12
8 | 3 | 2 | 15
9 | 3 | 3 | 16
(9 rows)
postgres=# select * from crosstab(
'select
site_id,
asset_type,
quantity
from
asset_quantities order by site_id,asset_type'
) as result(site_id int,asset_type_1_qty int,asset_type_2_qty int,asset_type_3_qty int);
site_id | asset_type_1_qty | asset_type_2_qty | asset_type_3_qty
---------+------------------+------------------+------------------
1 | 10 | 15 | 25
2 | 11 | 16 | 7
3 | 12 | 15 | 16
(3 rows)
哦,对了,在使用交叉表
函数之前,应该在PostgreSQL中执行下面的子句,否则会出现错误
CREATE EXTENSION tablefunc;
好的,这很容易实现,只需使用
自连接
,如下所示:
select
s1.site_id,
s1.quantity as asset_type_1_qty,
s2.quantity as asset_type_2_qty,
s3.quantity as asset_type_3_qty
from
asset_quantities s1
join
asset_quantities s2 on s1.site_id=s2.site_id and s1.asset_type=1 and s2.asset_type=2
join
asset_quantities s3 on s1.site_id=s3.site_id and s3.asset_type=3
order by
s1.quantity desc
postgres=# select * from asset_quantities;
id | site_id | asset_type | quantity
----+---------+------------+----------
1 | 1 | 1 | 10
2 | 1 | 2 | 15
3 | 1 | 3 | 25
4 | 2 | 1 | 11
5 | 2 | 2 | 16
6 | 2 | 3 | 7
7 | 3 | 1 | 12
8 | 3 | 2 | 15
9 | 3 | 3 | 16
(9 rows)
postgres=# select * from crosstab(
'select
site_id,
asset_type,
quantity
from
asset_quantities order by site_id,asset_type'
) as result(site_id int,asset_type_1_qty int,asset_type_2_qty int,asset_type_3_qty int);
site_id | asset_type_1_qty | asset_type_2_qty | asset_type_3_qty
---------+------------------+------------------+------------------
1 | 10 | 15 | 25
2 | 11 | 16 | 7
3 | 12 | 15 | 16
(3 rows)
好的,有一个名为交叉表的函数,它可以将行转换为列,我认为它将完全满足您的需要,如下所示:
select
s1.site_id,
s1.quantity as asset_type_1_qty,
s2.quantity as asset_type_2_qty,
s3.quantity as asset_type_3_qty
from
asset_quantities s1
join
asset_quantities s2 on s1.site_id=s2.site_id and s1.asset_type=1 and s2.asset_type=2
join
asset_quantities s3 on s1.site_id=s3.site_id and s3.asset_type=3
order by
s1.quantity desc
postgres=# select * from asset_quantities;
id | site_id | asset_type | quantity
----+---------+------------+----------
1 | 1 | 1 | 10
2 | 1 | 2 | 15
3 | 1 | 3 | 25
4 | 2 | 1 | 11
5 | 2 | 2 | 16
6 | 2 | 3 | 7
7 | 3 | 1 | 12
8 | 3 | 2 | 15
9 | 3 | 3 | 16
(9 rows)
postgres=# select * from crosstab(
'select
site_id,
asset_type,
quantity
from
asset_quantities order by site_id,asset_type'
) as result(site_id int,asset_type_1_qty int,asset_type_2_qty int,asset_type_3_qty int);
site_id | asset_type_1_qty | asset_type_2_qty | asset_type_3_qty
---------+------------------+------------------+------------------
1 | 10 | 15 | 25
2 | 11 | 16 | 7
3 | 12 | 15 | 16
(3 rows)
哦,对了,在使用交叉表
函数之前,应该在PostgreSQL中执行下面的子句,否则会出现错误
CREATE EXTENSION tablefunc;
你能举例说明结果吗?让我们更清楚地了解你想要什么。肖恩-我已经用一个示例结果更新了问题,我想给出答案。希望这对你有所帮助。你能给出一个示例结果吗?让我们更清楚地了解您想要什么。Shawn-我已经用示例结果更新了问题,我想给出答案。希望这对您有所帮助。谢谢Shawn。是否有一种方法可以使查询具有通用性,从而可以容纳任意数量的资产类型?目前,我只有3种资产类型,但用户在未来最多可以添加30种。在这种情况下,我不想加入30次,因为这会大大降低查询速度。好的,让我想想,然后给你一个更完美的答案,稍等几分钟。@user1066568我已经更新了我的答案,我认为它会完美地解决你的问题。祝你好运!谢谢,肖恩。是否有一种方法可以使查询具有通用性,从而可以容纳任意数量的资产类型?目前,我只有3种资产类型,但用户在未来最多可以添加30种。在这种情况下,我不想加入30次,因为这会大大降低查询速度。好的,让我想想,然后给你一个更完美的答案,稍等几分钟。@user1066568我已经更新了我的答案,我认为它会完美地解决你的问题。祝你好运!