我在 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,但数据库内处理更合适。
问题是密钥集事先未知。
所以没有单一语句(到服务器的单次往返)的解决方案。我们需要一个两步流程。喜欢:
第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$;
现在目标结构已经知道了,剩下的就很简单了。
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
: