Сравнить массив со столбцом массива в postgres - PullRequest
0 голосов
/ 05 ноября 2018
#  things               :string           is an Array

scope :things, ->(q) { where('ARRAY[?]::varchar[] IN things', Array.wrap(q)) }

scope :things, ->(q) { where('things && ARRAY[?]::varchar[]', Array.wrap(q)) }

scope :things, ->(q) { where('ARRAY[?]::varchar[] <@ things', Array.wrap(q)) }

Я пробовал несколько версий, но не могу найти правильное заклинание. Я ищу, чтобы найти любую строку, которая имеет какие-либо вещи в массиве ... есть ли перекрытие?

[1, 2, 3] & [1, 8] = t
[1, 2, 3] & [8, 9] = f

Я пытаюсь имитировать поведение ActiveRecord по умолчанию where. Если я дам ему массив, он получит все соответствующие строки. Возможно ли это с массивами postgres? Это даже эффективно?

1 Ответ

0 голосов
/ 05 ноября 2018

Один из способов сделать это - преобразовать массивы в набор строк. Если у вас есть массивы в виде набора строк, вы можете сделать пересечение между ними и проверить, является ли результат пустым набором.

Например:

CREATE TABLE my_test_table(id BIGINT, test_array BIGINT[]);
INSERT INTO my_test_table(id, test_array)
  VALUES
  (1, array[1,2,3]),
    (2, ARRAY[1,5,8]);

SELECT * FROM my_test_table
 WHERE  array_length((SELECT array
    (
        SELECT UNNEST(test_array)
        INTERSECT
        SELECT UNNEST(array[3,15,2])
    )), 1) > 0;

Результат вышеприведенного оператора SELECT:

1 | {1,2,3}

Это позволяет более сложное сопоставление элементов 2 массивов. Например, если вы хотите выбрать массивы, имеющие как минимум 2 общих элемента, вы можете просто изменить часть WHERE на

 WHERE  array_length((SELECT array
    (
        SELECT UNNEST(test_array)
        INTERSECT
        SELECT UNNEST(array[3,15,2])
    )), 1) > 1;
...