Ссылка на столбец неоднозначна в Postgres

#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 поведение.