Как и @ Абелисто прокомментировал , вы не можете ссылаться на SELECT
выражения списка из предложения WHERE
(или JOIN
) той же команды, потому что выражения в предложении WHERE
вычисляются первыми,Рассмотрим последовательность событий:
Вам нужен подзапрос или CTE, чтобы избежать повторениявыражение. Однако , ваши выражения не совсем совпадают с самого начала.Вы извлекаете простой текст как json
и используете то же самое, что и фактический text
в предложении JOIN.Извлечение сложно само по себе.Обратите внимание:
test=# SELECT json '"foo"' #>> '{}';
?column?
----------
foo
#>>
является оператором для ...
Получить объект JSON по указанному пути в виде текста
Передача пустого массива в виде пути ({}
) извлекает text
из простого текста json
.Похожие:
Теперь, чтобы избегать повторения путь извлечения, извлечение state
в CTE или в подзапросе и применение вышеупомянутого выражения во внешнем SELECT
:
SELECT DISTINCT ON (a.place_id)
a.state
, a.full_json -> 7 -> 'long_name' AS postal_code
, a.full_json <b>#> '{3,short_name}'</b> 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 = <b>t.state #>> '{}'</b> -- key element!
WHERE r.country_id = 1
-- ORDER BY place_id, ??? -- put expression(s) here to get deterministic pick
Эквивалент вашего оригинала.В то же время я упростил запрос, выделил CTE (не используйте CTE, если они не нужны до Postgres 12, они обычно добавляют стоимость) и добавил ORDER BY
, что потребуется для получения детерминированного результата.
О DISTINCT ON
& ORDER BY
:
Но вы уверены?Вы хотите postal_code
, city
и state
как тип json
?Это странное требование.
Кроме того, приведенный выше запрос может не дать наилучшего плана запроса.Ключом к производительности является поддержка наиболее селективных предикатов с оптимальными индексами.Повторение выражения вряд ли имеет значение.Вы могли бы хотеть это вместо этого:
SELECT DISTINCT ON (a.place_id)
a.full_json #>> '{5,short_name}' AS state
, a.full_json #>> '{7,long_name}' AS postal_code
, a.full_json #>> '{3,short_name}' AS city
FROM addresses_autocomplete a
JOIN regions r ON r.short_name = a.full_json #>> '{5,short_name}' -- back to repeating
WHERE a.formatted = $1
AND json_array_length(a.full_json) > 7
AND r.country_id = 1
-- ORDER BY a.place_id, ???