Я пытаюсь выбрать строку из таблицы, в которой:
- имеет минимальный UUID
- , на который нет ссылки в другой таблице
Но у меня возникают проблемы, когда я пытаюсь применить первое ограничение.
Вот все, что ожидается для целых чисел: во-первых, создайте таблицы, которые выглядят так:
t1
+----+---------+
| id | content |
+----+---------+
| 1 | a |
| 2 | b |
| 3 | c |
+----+---------+
и
t2
+----+---------+
| id | t1_id |
+----+---------+
| 1 | 1 |
+----+---------+
postgres=# create table t1(id int, content varchar(10), primary key (id));
CREATE TABLE
postgres=# create table t2(id int, t1_id int, foreign key (t1_id) references t1(id));
CREATE TABLE
postgres=# insert into t1 values (1, 'a');
INSERT 0 1
postgres=# insert into t1 values (2, 'b');
INSERT 0 1
postgres=# insert into t1 values (3, 'c');
INSERT 0 1
postgres=# insert into t2 values (1, 1);
INSERT 0 1
Теперь я хочу выбрать строку в t1
с наименьшим id
, который не отображается как внешний ключ в t2
.Я хочу выбрать строку в t1
, которая имеет id = 2
, и она работает должным образом:
postgres=# select min(t1.id) from t1 left outer join t2 on t1.id = t2.t1_id where t2.id is null;
min
-----
2
(1 row)
Однако, когда я пытаюсь сделать то же самое с UUID, в конечном запросе вообще ничего не возвращается.Обратите внимание, что я использовал ответ из этого поста , чтобы определить способ поиска минимальных UUID:
CREATE OR REPLACE FUNCTION min(uuid, uuid)
RETURNS uuid AS $$
BEGIN
IF $2 IS NULL OR $1 > $2 THEN
RETURN $2;
END IF;
RETURN $1;
END;
$$ LANGUAGE plpgsql;
create aggregate min(uuid) (
sfunc = min,
stype = uuid,
combinefunc = min,
parallel = safe,
sortop = operator (<)
);
Теперь создайте таблицы точно так же, как и раньше, используйте gen_random_uuid
для автоматической генерации UUID:
postgres=# drop table t2;
postgres=# drop table t1;
postgres=# create table t1(id uuid default gen_random_uuid(), content varchar(10), primary key (id));
postgres=# create table t2(id int, t1_id uuid, foreign key (t1_id) references t1(id));
postgres=# insert into t1(content) ('a');
postgres=# insert into t1(content) values ('a');
postgres=# insert into t1(content) values ('b');
postgres=# insert into t1(content) values ('c');
Мы успешно сделали три записи в t1
.Добавьте запись в t2
:
postgres=# select * from t1;
id | content
--------------------------------------+---------
b6148ae3-db56-4a4a-8d46-d5b4f04277ac | a
03abd324-8626-4fb1-9cb0-593373abf9ca | b
9f12b297-3f60-48a7-8282-e27c3aff1152 | c
(3 rows)
postgres=# insert into t2 values(1, '9f12b297-3f60-48a7-8282-e27c3aff1152');
Попробуйте выбрать строку из t1
с минимальным идентификатором, который не отображается в t2
, обратите внимание, что это не удается.
postgres=# select min(t1.id) from t1 left outer join t2 on t1.id = t2.t1_id where t2.id is null;
min
-----
(1 row)
Здесь мы показываем, что мы можем выбрать две не связанные записи в t1
, и мы можем выбрать минимальный UUID независимо:
postgres=# select t1.id from t1 left outer join t2 on t1.id = t2.t1_id where t2.id is null;
id
--------------------------------------
03abd324-8626-4fb1-9cb0-593373abf9ca
b6148ae3-db56-4a4a-8d46-d5b4f04277ac
(2 rows)
postgres=# select min(id) from t1;
min
--------------------------------------
03abd324-8626-4fb1-9cb0-593373abf9ca
(1 row)
Итак, что-то смешное происходит, когда я пытаюсь выбрать минимумUUID при попытке выполнить левое внешнее соединение.
РЕДАКТИРОВАТЬ: та же проблема существует при использовании not exists
:
postgres=# select min(id) from t1 where not exists (select t1_id from t2 where t2.t1_id = t1.id);
min
-----
(1 row)
, но проблема не появляется при использовании not in
:
postgres=# select min(id) from t1 where id not in (select t1_id from t2);
min
--------------------------------------
03abd324-8626-4fb1-9cb0-593373abf9ca
(1 row)