#sql #postgresql
Вопрос:
Пытаюсь упростить эту ВСТАВКУ и продолжаю получать эту неоднозначную ошибку ниже. Что я здесь делаю не так, нужен ли мне где-то псевдоним, которого мне не хватает?
<internal.PGError>: {
m: {
82: "scanRTEForColumn",
83: "ERROR",
86: "ERROR",
67: "42702",
77: "column reference "created_at" is ambiguous",
80: "3082",
70: "parse_relation.c",
76: "694",
},
}
Вот инструкция SQL, которую я использую:
INSERT INTO delivery_areas
SELECT
r.drn_id AS restaurant_drn_id,
'initial'::algorithm_name AS algorithm_name,
z.city_drn_id AS city_drn_id,
?::geometry AS delivery_area,
gen_random_uuid() AS drn_id,
?::timestamp AS created_at,
?::timestamp AS updated_at,
'custom'::delivery_area_type AS delivery_area_type
FROM restaurants r
JOIN neighborhood_zones nz ON (nz.hood_drn_id = r.hood_drn_id)
JOIN zones z ON (z.drn_id = nz.zone_drn_id)
WHERE r.drn_id = ?
GROUP BY restaurant_drn_id, algorithm_name, city_drn_id, created_at, updated_at, delivery_area_type
ON CONFLICT ON CONSTRAINT delivery_areas_pkey DO UPDATE
SET
delivery_area = EXCLUDED.delivery_area,
delivery_area_type = EXCLUDED.delivery_area_type,
updated_at = EXCLUDED.updated_at
RETURNING *
Создайте инструкции таблицы для областей доставки и ресторанов:
CREATE TYPE algorithm_name as ENUM ('initial');
CREATE TABLE delivery_areas (
restaurant_drn_id uuid NOT NULL,
algorithm_name algorithm_name NOT NULL DEFAULT 'initial',
city_drn_id uuid NOT NULL,
delivery_area geometry(MultiPolygon,4326) NOT NULL,
drn_id uuid NOT NULL DEFAULT gen_random_uuid(),
created_at timestamp without time zone NOT NULL,
updated_at timestamp without time zone NOT NULL,
PRIMARY KEY (restaurant_drn_id, algorithm_name)
);
CREATE INDEX delivery_areas_algorithm_city_idx on delivery_areas (algorithm_name, city_drn_id);
CREATE INDEX delivery_areas_delivery_area_idx on delivery_areas USING gist(delivery_area);
ALTER TABLE delivery_areas ADD FOREIGN KEY (restaurant_drn_id) REFERENCES restaurants(drn_id);
CREATE TABLE restaurants (
drn_id uuid PRIMARY KEY,
hood_drn_id uuid NOT NULL,
delivery_range_delta_m int4 NOT NULL,
geo_lat double precision NOT NULL,
geo_long double precision NOT NULL,
created_at timestamp without time zone NOT NULL,
updated_at timestamp without time zone NOT NULL
);
Комментарии:
1. Таким образом, все столбцы в delivery_areas находятся в инструкции select. И поскольку я не могу добавить псевдоним в инструкцию INSERT INTO, что я упускаю?
2. Квалифицируйте все ссылки на ваши столбцы, как
delivery_area
и должно бытьdelivery_areas.delivery_area
. Одна или несколько ссылок на ваши столбцы разрешаются двумя или более таблицами, и база данных просит вас устранить эту двусмысленность.3. Что
?::geometry AS delivery_area,
должно быть ? Заполнитель для позиционного аргумента?4.
?::geometry AS delivery_area,
действительно ли заполнитель для позиционного аргумента да5. Я добавил
delivery_areas.
в качестве префикса перед всеми именами полей справа внутри выбора, но теперь выдает следующую ошибку:<internal.PGError>: { 77: "syntax error at or near "."", ... }
Ответ №1:
Обратите внимание, что в вашем GROUP BY
предложении у вас есть ссылка на created_at
:
GROUP BY restaurant_drn_id, algorithm_name, city_drn_id, created_at, updated_at, delivery_area_type
Но этот столбец есть в нескольких ваших таблицах.
Префикс этой ссылки на столбец с правильной таблицей, например:
GROUP BY restaurant_drn_id, algorithm_name, city_drn_id, delivery_areas.created_at, updated_at, delivery_area_type
Я только догадался, на какую таблицу вы хотели сослаться. Это устранит эту ошибку, но это может быть не та дата/отметка времени, по которой вы хотели сгруппироваться.
Вот пример проблемы и решения, а также подробные сведения, которые следует указывать при задании такого рода вопросов:
CREATE TABLE delivery_areas (
id int
, created_at timestamp
);
CREATE TABLE restaurants (
drn_id int
, created_at timestamp
);
CREATE TABLE othertbl (
id int
, created_at timestamp
);
-- The following generates an error:
INSERT INTO delivery_areas
SELECT r.drn_id AS restaurant_drn_id
, current_timestamp AS created_at
FROM restaurants r
JOIN othertbl o
ON o.id = r.drn_id
GROUP BY restaurant_drn_id, created_at
;
-- ERROR: column reference "created_at" is ambiguous
-- LINE 7: GROUP BY restaurant_drn_id, created_at
-- The following is one way to resolve the error:
INSERT INTO delivery_areas
SELECT r.drn_id AS restaurant_drn_id
, current_timestamp AS created_at
FROM restaurants r
JOIN othertbl o
ON o.id = r.drn_id
GROUP BY restaurant_drn_id, r.created_at
;
Обратите внимание на r.created_at
. r
является определителем, разрешающим двусмысленность.
Вот ссылка на тестовый случай:
Комментарии:
1. Итак, у вас здесь противоречивые советы, я должен использовать
r.created_at
илиdelivery_areas.created_at
? Если я использую последнее, я получу это:72: "There is an entry for table "delivery_areas", but it cannot be referenced from this part of the query.",
2. @Уильямроуз Нет, нет. Вы посмотрели ссылку на скрипку, которую я предоставил?
r.created_at
был в тестовом примере, который я создал. Я также сослался на ваш запрос, добавленный в начало ответа. Вы знаете, какуюcreated_at
колонку вы хотелиGROUP BY
?3. Ааа, хорошо. Да, я хотел бы сгруппироваться по
delivery_areas
версии4. @WilliamRose Идеально. Тогда мое предположение должно сработать, пока не будет найдена следующая проблема.
5. @WilliamRose
SELECT
Список определяет, что будет вставлено.tbl.created_at
ВGROUP BY
термины не вставляется, но используется для определения того, какие строки выбраны. Мы могли бы поболтать, если хочешь. Я не уверен, что вы понимаете такоеGROUP BY
поведение.