避免在SELECT列表和WHERE子句中重复表达式

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

我有一个基本的查询,该查询从google自动完成转储的数据中获取行,其中包含place_id,格式化的地址和一个包含整个json对象的json列。我相信我正在使用Postgres 10或11。

WITH 
    t AS (
        SELECT place_id,formatted,full_json 
        FROM addresses_autocomplete 
        WHERE json_array_length(full_json) > 7
    ), 
    r AS (
        SELECT short_name FROM regions WHERE regions.country_id = 1
    )
SELECT DISTINCT ON(place_id) 
    t.full_json->5->'short_name' AS state, 
    t.full_json->7->'long_name' as postal_code, 
    full_json->3->'short_name' AS city 
FROM t 
INNER JOIN r ON r.short_name = t.full_json->5->>'short_name' 
WHERE t.formatted=$1;

有什么办法可以写我的查询,使t.full_json->5->'short_name'不再重复?

sql json postgresql join greatest-n-per-group
1个回答
0
投票

[类似于@Abelisto commented,您不能从同一命令的SELECT(或WHERE)子句引用JOIN列表表达式,因为WHERE子句中的表达式首先被求值。考虑事件的顺序:

您需要一个子查询或CTE,以避免重复该表达式。 但是,开始时的表达式并不完全相同。您将简单文本提取为json,并在JOIN子句中使用与实际text相同的文本。提取本身就很棘手。试想一下:

test=# SELECT json '"foo"' #>> '{}';
 ?column?
----------
 foo

#>>是...的运算符]

将指定路径的JSON对象作为文本获取

将空数组作为路径(#>>)传递会从简单的{}文本中提取text。相关阅读:

  • json
  • 现在,到避免重复

提取路径,在CTE或子查询中提取Postgres: How to convert a json string to text?,并在外部state中应用上述表达式:
SELECT

相当于您的原件。在此过程中,我简化了查询,内联了CTE(除非在Postgres 12之前不需要使用CTE,否则它们通常会增加成本)并添加了SELECT DISTINCT ON (a.place_id) a.state , a.full_json -> 7 -> 'long_name' AS postal_code , a.full_json #> '{3,short_name}' AS city -- alternative syntax, btw. FROM ( SELECT full_json -> 5 -> 'short_name' AS state -- once! , full_json FROM addresses_autocomplete WHERE json_array_length(full_json) > 7 AND formatted = $1 ) a JOIN regions r ON r.short_name = t.state #>> '{}' -- key element! WHERE r.country_id = 1 -- ORDER BY place_id, ??? -- put expression(s) here to get deterministic pick,这将需要获得确定性结果。

关于ORDER BYDISTINCT ON

此外,以上查询可能不会产生最佳的查询计划。性能的关键是用最佳索引支持最有选择性的谓词。重复表达几乎没有关系。您可能需要这样:

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