Как я могу назначить несколько значений, возвращаемых из подзапроса, по одной каждой строке в моем основном запросе в Postgres? - PullRequest
0 голосов
/ 25 февраля 2020

У меня есть две таблицы:

netflix1=# \d+ rental
                                                                    Table "public.rental"
       Column       |              Type              | Collation | Nullable |                 Default                 | Storage | Stats target | Description
--------------------+--------------------------------+-----------+----------+-----------------------------------------+---------+--------------+-------------
 rentalid           | numeric(16,0)                  |           | not null | nextval('rental_pk_sequence'::regclass) | main    |              |
 memberid           | numeric(12,0)                  |           | not null |                                         | main    |              |
 dvdid              | numeric(16,0)                  |           | not null |                                         | main    |              |
 rentalrequestdate  | timestamp(3) without time zone |           | not null |                                         | plain   |              |
 rentalshippeddate  | timestamp(3) without time zone |           |          |                                         | plain   |              |
 rentalreturneddate | timestamp(3) without time zone |           |          |                                         | plain   |              |
 dvd_copy_id        | numeric(10,0)                  |           |          |                                         | main    |              |
Indexes:
    "rental_rentalid_pk" PRIMARY KEY, btree (rentalid)
    "rental_dvd_copy_id_key" UNIQUE CONSTRAINT, btree (dvd_copy_id)
Foreign-key constraints:
    "rental_dvdid_fk" FOREIGN KEY (dvdid) REFERENCES dvd(dvdid)
    "rental_memberid_fk" FOREIGN KEY (memberid) REFERENCES member(memberid)
Access method: heap

Другая таблица:

netflix1=# \d+ dvd_copy
                                                          Table "public.dvd_copy"
   Column    |     Type      | Collation | Nullable |                    Default                    | Storage | Stats target | Description
-------------+---------------+-----------+----------+-----------------------------------------------+---------+--------------+-------------
 dvd_copy_id | integer       |           | not null | nextval('dvd_physical_copy_id_seq'::regclass) | plain   |              |
 dvdid       | numeric(10,0) |           | not null |                                               | main    |              |
Indexes:
    "dvd_copy_pkey" PRIMARY KEY, btree (dvd_copy_id)
Foreign-key constraints:
    "dvd_copy_dvdid_fkey" FOREIGN KEY (dvdid) REFERENCES dvd(dvdid)
Access method: heap

Я хочу присвоить столбцу dvd_copy_id в аренду его причитающиеся значения, используя dvdid в качестве общего столбец в двух таблицах. Тем не менее, dvdid не уникален в таблице dvd_copy, и поэтому я хочу что-то вроде следующего:

Скажем dvdid = 4 имеет 5 счетчиков в таблице dvdcopy, я хочу все 5 значений dvd_copy_id соответствует dvdid, назначаемому в таблице аренды.

Некоторые данные: dvd_copy:

netflix1=# select * from dvd_copy;
 dvd_copy_id | dvdid
-------------+-------
           1 |     3
           2 |     1
           3 |     6
           4 |     7
           5 |     5
           6 |     2
           7 |     2
           8 |     4
           9 |     4
          10 |     4
          11 |     4
          12 |     4
(12 rows)

Некоторые данные из таблицы аренды:

netflix1=# select * from rental;
 rentalid | memberid | dvdid |  rentalrequestdate  |  rentalshippeddate  | rentalreturneddate  | dvd_copy_id
----------+----------+-------+---------------------+---------------------+---------------------+-------------
        1 |        1 |     4 | 2019-02-02 00:00:00 | 2019-02-02 00:00:00 | 2019-02-09 00:00:00 |
        2 |        1 |     6 | 2019-02-02 00:00:00 | 2019-02-02 00:00:00 | 2019-02-09 00:00:00 |
        3 |        1 |     3 | 2019-02-02 00:00:00 | 2019-02-02 00:00:00 | 2019-02-09 00:00:00 |
        4 |        5 |     4 | 2019-02-15 00:00:00 | 2019-02-15 00:00:00 |                     |
        5 |        5 |     5 | 2019-02-15 00:00:00 | 2019-02-15 00:00:00 |                     |
        6 |       15 |     1 | 2019-02-12 00:00:00 | 2019-02-12 00:00:00 | 2019-02-21 00:00:00 |
        7 |        9 |     2 | 2019-02-19 00:00:00 | 2019-02-19 00:00:00 |                     |
        8 |        8 |     2 | 2019-02-20 00:00:00 | 2019-02-21 00:00:00 |                     |
        9 |        1 |     4 | 2019-02-20 00:00:00 | 2019-02-20 00:00:00 |                     |
       10 |       15 |     7 | 2019-02-28 00:00:00 |                     |                     |
       11 |        2 |     4 | 2004-02-02 00:00:00 |                     |                     |
       12 |        2 |     4 | 2004-02-03 00:00:00 |                     |                     |
(12 rows)

Это мой запрос:

netflix1=# update rental set dvd_copy_id = (select dvd_copy_id from dvd_copy where dvdid=dvd_copy.dvdid)
;
ERROR:  more than one row returned by a subquery used as an expression

Я понимаю, что должна быть оконная функция, но я не могу ее сформировать.

Как назначить dvd_copy_id значения для каждой строки в rental стол?

1 Ответ

1 голос
/ 25 февраля 2020

Вы не можете сделать это в одном запросе. Функция окна не поможет; проблема заключается в видимости данных.

Простое добавление limit 1 в подзапрос не сработает, потому что многие прокаты могут получить один и тот же dvd_copy_id. Создание подзапроса наподобие (select dvd_copy_id from dvd_copy where dvdid=dvd_copy.dvdid and not exists (select 1 from rental where dvd_copy_id=dvd_copy.dvdid) limit 1 также не будет работать, потому что каждый оператор видит базу данных, как это было, когда оператор начал выполнять , поэтому, когда первая строка UPDATE d с dvd_copy_id, когда Обновление перейдет к следующей строке, select 1 from rental where dvd_copy_id=dvd_copy.dvdid увидит строки rental без обновленных данных, и вы все равно получите дубликаты dvd_copy_ids.

Характер того, что вы делаете - где вам нужно, чтобы dvd_copy_id каждой строки rental находился под влиянием модификаций других строк rental - требуется наличие как минимум одного отдельного оператора на модификацию, на который мог повлиять предыдущий UPDATE.

С практической точки зрения, я бы справился с этим, собрав UPDATE, который работал для одной строки, дублируя его несколько раз в формате .txt и передав его в psql. Да серьезно. Некрасиво но работает:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...