如何使用PL/pgSQL构造具有动态列的表
我有一个Postgres表,名为如何使用PL/pgSQL构造具有动态列的表,sql,postgresql,plpgsql,dynamic-sql,crosstab,Sql,Postgresql,Plpgsql,Dynamic Sql,Crosstab,我有一个Postgres表,名为位置。它有几百万行,数据格式如下 id | location_a | location_b ----+--------------+-------------- 36 | Sydney | London 37 | Atlanta | London 38 | New York | Tokyo 39 | Tokyo | Sydney 40 | Tokyo | Sydney ..... 我希望
位置
。它有几百万行,数据格式如下
id | location_a | location_b
----+--------------+--------------
36 | Sydney | London
37 | Atlanta | London
38 | New York | Tokyo
39 | Tokyo | Sydney
40 | Tokyo | Sydney
.....
我希望能够生成以下形式的透视表/计数-
问题是列的数量是可变的,因此必须通过编程/动态确定,而不是使用静态SELECT
查询
我理解PL/pgSQL的基本概念,因为它是一种脚本语言,可以让我做这样的动态事情
但是我在开始的时候遇到了很多麻烦。有没有一种简单的方法来计算上述各项 您可以动态创建视图。下面介绍了一个比您更简单的案例的想法和解决方案,请在继续之前阅读 我们将使用以下查询创建视图:
with all_locations(location) as (
select distinct location_a
from locations
union
select distinct location_b
from locations
)
select location_a as location, json_object_agg(location_b, count order by location_b) as data
from (
select a.location as location_a, b.location as location_b, count(l.*)
from all_locations a
cross join all_locations b
left join locations l on location_a = a.location and location_b = b.location
group by 1, 2
) s
group by 1
order by 1;
结果:
location | data
----------+----------------------------------------------------------------------------
Atlanta | { "Atlanta" : 0, "London" : 1, "New York" : 0, "Sydney" : 0, "Tokyo" : 0 }
London | { "Atlanta" : 0, "London" : 0, "New York" : 0, "Sydney" : 0, "Tokyo" : 0 }
New York | { "Atlanta" : 0, "London" : 0, "New York" : 0, "Sydney" : 0, "Tokyo" : 1 }
Sydney | { "Atlanta" : 0, "London" : 1, "New York" : 0, "Sydney" : 0, "Tokyo" : 0 }
Tokyo | { "Atlanta" : 0, "London" : 0, "New York" : 0, "Sydney" : 2, "Tokyo" : 0 }
(5 rows)
城市列表将在函数中使用两次,因此它存储在数组cities
中。请注意,您可以将函数中的第一个查询替换为一个更简单的查询(它只是不同城市的有序列表)
使用该功能并从创建的视图中选择数据:
select create_locations_view();
select * from locations_view;
location | Atlanta | London | New York | Sydney | Tokyo
----------+---------+--------+----------+--------+-------
Atlanta | 0 | 1 | 0 | 0 | 0
London | 0 | 0 | 0 | 0 | 0
New York | 0 | 0 | 0 | 0 | 1
Sydney | 0 | 1 | 0 | 0 | 0
Tokyo | 0 | 0 | 0 | 2 | 0
(5 rows)
我多次使用这种方法,但我没有处理过真正大数据的经验,因此我不能保证它的效率。仔细研究使用方法,但即使在这种情况下,您仍必须在查询中列出城市名称。据我所知,在postgres中无法达到您想要的结果。如果选择function创建动态表,则必须再次设置返回类型table和所有要返回的列。但您不希望这样做,因为您需要一个动态列。Postgres在执行查询和根据查询生成表方面与MySQL不同,如果“用动态列构造表”的意思是
CREATE table
,那么就可以了。如果您的目标是一个直接返回动态列数的表函数,那么您就不走运了:这是不可能做到的。不过,您可以返回数组或json等形式的聚合数据。相关:。首先明确您需要什么,公开您的Postgres版本,并提供源表的精确定义(CREATE table…
)。谢谢,这是一个非常有创意的解决方案!这比我希望的要长,但总体来说,似乎没有太多人支持这样做。感谢您的帮助。某些限制和现成工具的缺乏源于数据库理论的基础。基本上,这种数据转换属于表示层,应该在客户端执行。请注意,通过转换第一个查询的结果(使用jsonb列),可以相对容易地在应用程序中获得所需的效果。另一方面,答案中描述的函数实际上包含的代码不多,也不是特别复杂,尽管需要一些高级知识。
select create_locations_view();
select * from locations_view;
location | Atlanta | London | New York | Sydney | Tokyo
----------+---------+--------+----------+--------+-------
Atlanta | 0 | 1 | 0 | 0 | 0
London | 0 | 0 | 0 | 0 | 0
New York | 0 | 0 | 0 | 0 | 1
Sydney | 0 | 1 | 0 | 0 | 0
Tokyo | 0 | 0 | 0 | 2 | 0
(5 rows)