Как проверить, находится ли поплавок между несколькими диапазонами в Postgres? - PullRequest
0 голосов
/ 08 ноября 2019

Я пытаюсь написать запрос следующим образом:

SELECT * FROM table t
WHERE ((long_expression BETWEEN -5 AND -2) OR 
       (long_expression BETWEEN 0 AND 2) OR 
       (long_expression BETWEEN 4 and 6))

Где long_expression примерно равно этому:

(((t.s <#> (SELECT s FROM user WHERE user.user_id = $1)) / (SELECT COUNT(DISTINCT cluster_id) FROM cluster) * -1) + 1)

t.s и s являютсяCUBE типы данных и <#> - индексированный оператор расстояния.

Я мог бы просто повторить это длинное выражение несколько раз в теле, но это было бы чрезвычайно многословно. Альтернативой может быть как-то сохранить ее в переменной (с CTE?), Но я думаю, что это может исключить возможность использования индекса в предложении WHERE?

Я также нашел int4range и numrange, но я не верю, что они также будут работать здесь, потому что оператор расстояния возвращает float8, а не целое число или числа.

1 Ответ

1 голос
/ 08 ноября 2019

Вы можете использовать боковое соединение:

SELECT t.*
FROM table t CROSS JOIN LATERAL
     (VALUES (long_expression)) v(x)
WHERE ((v.x BETWEEN -5 AND -2) OR 
       (v.x BETWEEN 0 AND 2) OR 
       (v.x BETWEEN 4 and 6)
      );

Конечно, можно использовать CTE или подзапрос;Мне нравятся боковые объединения, потому что они легко выражают несколько выражений, которые зависят от предыдущих значений.

...