У меня есть таблица с внешним ключом и логическим значением (и куча других столбцов, которые здесь не релевантны), например:
CREATE TABLE myTable
(
someKey integer,
someBool boolean
);
insert into myTable values (1, 't'),(1, 't'),(2, 'f'),(2, 't');
Каждый someKey может иметь 0 или более записей. Для любого заданного someKey мне нужно знать, если a) все записи верны, или b) любые записи являются ложными (в основном, AND).
Я придумал следующую функцию:
CREATE FUNCTION do_and(int4) RETURNS boolean AS
$func$
declare
rec record;
retVal boolean = 't'; -- necessary, or true is returned as null (it's weird)
begin
if not exists (select someKey from myTable where someKey = $1) then
return null; -- and because we had to initialise retVal, if no rows are found true would be returned
end if;
for rec in select someBool from myTable where someKey = $1 loop
retVal := rec.someBool AND retVal;
end loop;
return retVal;
end;
$func$ LANGUAGE 'plpgsql' VOLATILE;
... что дает правильные результаты:
select do_and(1) => t
select do_and(2) => f
select do_and(3) => null
Мне интересно, есть ли лучший способ сделать это. В этом простом сценарии это выглядит не так уж и плохо, но как только вы включите весь поддерживающий код, он станет длиннее, чем хотелось бы. Я посмотрел на приведение столбца someBool к массиву и использование конструкции ALL, но я не мог заставить его работать ... какие-нибудь идеи?