将 hstore 分解为行内的新列

问题描述 投票:0回答:1

我在 PostgreSQL 中有下表。

hstore
扩展已激活。

osm_id hstore_column
172544 "路缘"=>"降低", "高速公路"=>"人行横道", "人行横道"=>"有标记", "crossing_ref"=>"斑马线", "tactile_paaving"=>"是", "crossing_island"= >“是”,“crossing_markings”=>“斑马”
172548 “巴士”=>“是”,“名称”=>“伦敦大街”,“ref_BVG”=>“103010”,“网站”=>“https_//qr.bvg.de/h103010”,“public_transport” =>“停止位置”
458330 “ref”=>“7”,“名称”=>“Kaiserdamm”,“高速公路”=>“motorway_junction”,“目的地”=>“Kaiserdamm”

我想将

hstore_column
分解为每个键的列。

表格标题应该变成

osm_id 路边 高速公路 穿越 crossing_ref 触觉 穿越岛屿 交叉标记 巴士 名字 ref_BVG 网站 公共交通 参考 目的地
172544 降低 穿越 已标记 斑马 是的 是的 斑马

这个相关答案要求已知密钥。
问题是密钥集事先是未知的。

在此相关答案中给定的函数在 hstore 列中作为标签出现的关键字存在问题。

有没有办法动态地将 hstore 键分解为同一个表中的单列?我知道的唯一解决方案是Python,但数据库内处理更合适。

postgresql dynamic-sql hstore
1个回答
0
投票

问题是密钥集事先未知。

所以没有单一语句(到服务器的单次往返)的解决方案。我们需要一个两步流程。喜欢:

第1步:确定键集,并从中动态创建临时表以隐式临时注册复合类型。 (还有各种其他方式来引导收集到的信息,这似乎是最方便的):

DO
$do$
BEGIN
   DROP TABLE IF EXISTS pg_temp.osm_exploded;  -- optional
   
   EXECUTE (
   SELECT format('CREATE TEMP TABLE osm_exploded(%s);'
               , string_agg(quote_ident(key) || ' text', ', '))
   FROM (
      SELECT DISTINCT key
      FROM   tbl, skeys(hstore_column) key
      ORDER  BY key  -- or whatever order you need ?
      ) sub
   );
END   
$do$;

现在目标结构已经知道了,剩下的就很简单了。

第 2 步: 使用

populate_record()
:

进行简单查询
SELECT t.osm_id, o.*
FROM   tbl t, populate_record(null::osm_exploded, t.hstore_column) o

小提琴

隐式

CROSS JOIN LATERAL
是安全的,因为
populate_record()
始终返回一行。 (返回“无行”的集合返回函数将消除结果行,您可能需要使用
LEFT JOIN ... ON true
。)

与替代可行解决方案相关的答案,一种拼写出 SELECT 列表中的所有键,一种使用附加模块中的

crosstab()
tablefunc

© www.soinside.com 2019 - 2024. All rights reserved.