Как я могу выполнить И на неизвестном количестве булевских переменных в postgresql?

Используя преимущества сравнения объектов bool и tuple, это легко записать как

(current_section=="PM",current_hour%12,current_minute)<(due_section=="PM",due_hour%12,due_minute)

. Конечно, канонизация числом минут с полуночи является более общей: 111]

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

7
задан GEOCHET 25 March 2009 в 22:57
поделиться

7 ответов

Нет необходимости для переопределения функций PostgreSQL уже предоставляет: bool_and () выполнит работу:

select bool_and(someBool)
  from myTable
  where someKey = $1
  group by someKey;

(извините, не могу сейчас это проверить)

7
ответ дан 6 December 2019 в 14:09
поделиться

Подобный предыдущему, но в одном запросе, это добьется цели, однако, это не чистый ни легко понятный код:

SELECT someKey, 
  CASE WHEN sum(CASE WHEN someBool THEN 1 ELSE 0 END) = count(*)
                    THEN true 
                    ELSE false END as boolResult
FROM  table
GROUP BY someKey

Это получит все ответы сразу, если Вы только захотите один ключ, просто добавляют оператор Where

3
ответ дан 6 December 2019 в 14:09
поделиться

Я просто установил PostgreSQL впервые на этой неделе, таким образом, необходимо будет очистить синтаксис, но общее представление здесь должно работать:

return_value = NULL

IF EXISTS
(
     SELECT
          *
     FROM
          My_Table
     WHERE
          some_key = $1
)
BEGIN
     IF EXISTS
     (
          SELECT
               *
          FROM
               My_Table
          WHERE
               some_key = $1 AND
               some_bool = 'f'
     )
          SELECT return_value = 'f'
     ELSE
          SELECT return_value = 't'
END

Идея состоит в том, что только необходимо посмотреть на одну строку, чтобы видеть, существует ли кто-либо и если по крайней мере одна строка существует, затем только необходимо посмотреть, пока Вы не находите, что ложное значение решает, что окончательное значение является ложью (или Вы добираетесь в конец, и это верно). Предположение, что у Вас есть индекс на some_key, производительность, должно быть хорошим, я думал бы.

2
ответ дан 6 December 2019 в 14:09
поделиться

Возможно, считайте 'все' объекты с somekey=somevalue и используйте его в булевом сравнении с количеством всех 'Истинных' происшествий для somekey?

Некоторые не протестировали pseudo-sql для показа то, что я имею в виду...

select foo1.count_key_items = foo2.count_key_true_items
from
   (select count(someBool) as count_all_items from myTable where someKey = '1') as foo1,
   (select count(someBool) as count_key_true_items from myTable where someKey = '1' and someBool) as foo2
0
ответ дан 6 December 2019 в 14:09
поделиться
CREATE FUNCTION do_and(int4)
  RETURNS boolean AS
$BODY$
  SELECT
    MAX(bar)::bool
  FROM (
    SELECT
      someKey,
      MIN(someBool::int) AS bar
    FROM
      myTable
    WHERE
      someKey=$1
    GROUP BY
      someKey

    UNION

    SELECT
      $1,
      NULL
  ) AS foo;
$BODY$
  LANGUAGE 'sql' STABLE;

В случае, если Вам не нужно Нулевое значение (когда нет никаких строк), просто используйте запрос ниже:

SELECT
  someKey,
  MIN(someBool::int)::bool AS bar
FROM
  myTable
WHERE
  someKey=$1
GROUP BY
  someKey
0
ответ дан 6 December 2019 в 14:09
поделиться

(Очень второстепенный аспект: я думаю, что ваша функция должна быть объявлена ​​STABLE, а не VOLATILE, поскольку она просто использует данные из базы данных для определения своего результата.)

Как кто-то упомянул, Вы можете остановить сканирование, как только вы встретите «ложное» значение. Если это распространенный случай, вы можете использовать курсор, чтобы фактически вызвать «быстрое завершение»:

CREATE FUNCTION do_and(key int) RETURNS boolean
  STABLE LANGUAGE 'plpgsql' AS $$
DECLARE
  v_selector CURSOR(cv_key int) FOR
    SELECT someBool FROM myTable WHERE someKey = cv_key;
  v_result boolean;
  v_next boolean;
BEGIN
  OPEN v_selector(key);
  LOOP
    FETCH v_selector INTO v_next;
    IF not FOUND THEN
      EXIT;
    END IF;
    IF v_next = false THEN
      v_result := false;
      EXIT;
    END IF;
    v_result := true;
  END LOOP;
  CLOSE v_selector;
  RETURN v_result;
END
$$;

Этот подход также означает, что вы выполняете только один просмотр myTable. Имейте в виду, я подозреваю, что вам нужны нагрузки и ряды строк, чтобы разница была заметной.

2
ответ дан 6 December 2019 в 14:09
поделиться
SELECT  DISTINCT ON (someKey) someKey, someBool
FROM    myTable m
ORDER BY
        someKey, someBool NULLS FIRST

При этом будет выбрано первое упорядоченное логическое значение для каждого someKey .

Если имеется одно значение FALSE или NULL , он будет возвращен первым, что означает, что выполнение И завершилось ошибкой.

Если первое логическое значение - ИСТИНА , то все остальные логические значения также будут ИСТИНА для этого ключа.

В отличие от агрегата, здесь будет использоваться индекс на (someKey, someBool) .

Чтобы вернуть OR , просто измените порядок:

SELECT  DISTINCT ON (someKey) someKey, someBool
FROM    myTable m
ORDER BY
        someKey, someBool DESC NULLS FIRST
0
ответ дан 6 December 2019 в 14:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: