Путаница сравнения массивов Postgres - PullRequest
1 голос
/ 22 марта 2012

Когда я бегу

select array[19,21,500] <= array[23,5,0]; 

, я получаю истину.

, но когда я бегу

select array[24,21,500] <= array[23,5,0]; 

, я получаю ложь.Это говорит о том, что сравнение проводится только по первому элементу.

Мне интересно, существует ли оператор или, возможно, функция, которая сравнивает все записи так, что, если все записи в левом массиве меньше, чем вПравый массив (с тем же индексом) вернул бы true, иначе вернул бы false.

Я надеюсь получить все строки, которые имеют весь массив «меньше» или «больше» данного массива.Я не знаю, возможно ли это.

Ответы [ 2 ]

2 голосов
/ 26 марта 2013

Массивы используют ординальность в качестве основного свойства. Другими словами '{1,3,2}' <> '{1,2,3}', и это важно понимать, глядя на сравнения. Они смотрят на последовательные элементы.

Представьте на мгновение, что PostgreSQl не имеет типа inet. Мы могли бы использовать int [] для указания блоков cidr. Например, мы могли бы видеть это как '{10,0,0,1,8}' для представления 10.0.0.1/8. Мы могли бы сравнить IP-адреса на этом пути. Мы также можем представить как bigint как: '{167772161,8}' В этом сравнении, если у вас есть два IP-адреса с разными подсетями, мы можем сравнить их, и тот, который имеет более конкретную подсеть, последует за тем, который имеет менее конкретную подсеть. .

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

В случае, если вы хотите создать оператор, который не уважает ординальность, вы можете создать свой собственный. По сути, вы создаете функцию, которая возвращает bool на основе этих двух значений, а затем заключаете ее в оператор (см. CREATE OPERATOR в документации для получения дополнительной информации о том, как это сделать). Вы ни в коем случае не ограничены тем, что PostgreSQL предлагает из коробки.

1 голос
/ 26 марта 2013

Чтобы фактически выполнить запрошенную операцию, используйте unnest() параллельно и в совокупности с bool_and():

SELECT bool_and(a <  b) -- each element < corresponding element in 2nd array
      ,bool_and(a <= b)
      ,bool_and(a >= b)
      ,bool_and(a >  b)
       -- etc.
FROM  (SELECT unnest('{1,2,3}'::int[]) AS a, unnest('{2,3,4}'::int[]) AS b) t

Оба массива должны иметь одинаковое количество базовых элементов , чтобы их нельзя было параллельно выводить. Иначе вы получите CROSS JOIN, то есть совершенно другой результат.

...