Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/37.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
如何使用PL/pgSQL构造具有动态列的表_Sql_Postgresql_Plpgsql_Dynamic Sql_Crosstab - Fatal编程技术网

如何使用PL/pgSQL构造具有动态列的表

如何使用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 ..... 我希望

我有一个Postgres表,名为
位置
。它有几百万行,数据格式如下

 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)