Как правильно добавить несколько AND и BETWEEN в SQL-запрос? - PullRequest
0 голосов
/ 21 декабря 2018

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

Я пытаюсь построить функцию фильтрации, где пользователи могут фильтровать между диапазонами, например: цена: от 100 $ до 200 $ и квадратные футы между 30 и 80.

Мой подход выглядиткак это:

SELECT * FROM 'tableXY' WHERE value BETWEEN 100 AND 200 AND key ='price' 
AND value BETWEEN 2 AND 5 AND key = 'rooms'
AND value BETWEEN 40 AND 80 AND key = 'sqft'......and so on.

Таблица содержит столбцы id, foreign_id, key и value.Ключами в строках являются цена, sqft, комнаты, адреса и т. Д. Если я фильтрую для определенного ценового диапазона между ценой x и ценой y и комнатами между n комнатами и m комнатами, он должен возвращать результаты только в том случае, если был применен установленный ошибочный фильтрк.

С моим подходом не найдено никаких результатов, и если я использую ИЛИ вместо И, он также показывает Результаты, к которым другие фильтры не применимы.

Ответы [ 5 ]

0 голосов
/ 21 декабря 2018

С таблицами пар ключ-значение, как указано в вашем сообщении, ваши данные представлены в формате long , где различные типы единиц значений и индикаторов находятся в двух столбцах: key и значение .Следовательно, каждое условие AND пытается выбрать одну пару условий логики key и value и не может встретить все сразу, если только такие значения, как цена , комнаты и sqft хранятся в своих определенных столбцах в формате wide .

Долгосрочное решение

Существует длинный вопрос об использовании модели значений атрибутов сущностей, такой как SO post в реляционных базах данных.Долгосрочное решение для эффективной фильтрации взаимно включающих условий состоит в том, чтобы перестроить вашу таблицу в широкоформатный формат, где значения находятся в своих собственных столбцах и где запросы намного проще с условиями AND.

CREATE TABLE tableXY (
    `price` DOUBLE,
    `room` INT
    `sqlft` INT,
    ... OTHER indicators ...
);

SELECT * 
FROM tableXY 
WHERE `price` BETWEEN 100 AND 200
  AND `rooms` BETWEEN 2 AND 5
  AND `sqft` BETWEEN 40 AND 80

Краткосрочное решение

Но краткосрочным решением для существующего длинного формата является запуск условных агрегаций для создания «псевдостолбцов» значений: цена , комнаты , sqft .Добавьте GROUP BY для любых статических атрибутов (имена, местоположения, время и т. Д.).

CREATE TABLE tableXY (
    `key` VARCHAR(10),
    `value` INT
);

SELECT sub.* 
FROM 
   (SELECT CASE WHEN `key` = 'name' THEN `key` ELSE NULL END AS `name`,
           SUM(CASE 
                   WHEN `key` = 'price'
                   THEN `value`
                   ELSE NULL
               END) AS price,
           SUM(CASE 
                   WHEN `key` = 'rooms' 
                   THEN `value`
                   ELSE NULL
               END) AS rooms,
           SUM(CASE 
                   WHEN `key` = 'sqlft' 
                   THEN `value
                   ELSE NULL
               END) AS sqft,

           -- ...other values...

     FROM tableXY

     GROUP BY CASE WHEN `key` = 'name' THEN `key` ELSE NULL END
  ) AS sub

WHERE sub.price BETWEEN 100 AND 200
  AND sub.rooms BETWEEN 2 AND 5
  AND sub.sqft BETWEEN 40 AND 80
0 голосов
/ 21 декабря 2018

Если вы использовали объединение аналогично:

QueryWithRoomCostFilter UNION  QueryWithRoomSizeFilter

Тогда получится набор кортежей, который соответствует вашему фильтру затрат 100 $ -200 $, и добавит их в набор результатовЗатем он оценит второй запрос с фильтром для комнаты размером 40-80 кв. футов и добавит эти кортежи в набор результатов, эффективно комбинируя (принимая объединение) обоих результатов.В этом случае вы могли видеть, что объединение работает так, как если бы у вас было ИЛИ между вашими условиями.

Я не использую значение и между часто, но, возможно, попробуйте что-то в этом духе и дайте нам знать, еслиэто все еще не работает.

SELECT * 
FROM table_name
WHERE (price BETWEEN 100 AND 200)
AND (rooms BETWEEN 2 AND 5)
AND (sqft BETWEEN 40 AND 80)
0 голосов
/ 21 декабря 2018

Похоже, вам нужна логическая операция or между каждой парой условий на value и key:

SELECT *
FROM   tableXY
WHERE  (value BETWEEN 100 AND 200 AND key ='price' ) OR 
       (value BETWEEN   2 AND   5 AND key = 'rooms') OR
       (value BETWEEN  40 AND  80 AND key = 'sqft' ) -- etc...

Примечание. Поскольку and имеет более высокий приоритет, чем orскобки не нужны, но они облегчают чтение запроса.

0 голосов
/ 21 декабря 2018

Решение 1 : Используйте or между условиями для различных значений ключа.

SELECT * FROM 'tableXY' WHERE (value BETWEEN 100 AND 200 AND key ='price') 
OR (value BETWEEN 2 AND 5 AND key = 'rooms')
OR (value BETWEEN 40 AND 80 AND key = 'sqft')......and so on.

Решение 2 : Вам необходимо использовать case when

SELECT * FROM 'tableXY' 
WHERE 1 = (
 case 
  when key ='price' and value BETWEEN 100 AND 200 
     then 1
  when key ='rooms' and value BETWEEN 2 AND 5
     then 1
.....
  else 0
 end
) 

Вот почему в вашем первоначальном предложении не было найдено записей.Ваш первоначальный подход с использованием AND между наборами условий в основном выбирает WHERE ... value BETWEEN 2 AND 5 AND... value BETWEEN 40 AND 80 Очевидно, что никакого результата

0 голосов
/ 21 декабря 2018

Я думаю, что вы хотите агрегации, потому что значения находятся в разных строках:

SELECT something
FROM tableXY
GROUP BY something 
HAVING SUM( value BETWEEN 100 AND 200 AND key ='price' ) > 0 AND
       SUM( value BETWEEN 2 AND 5 AND key = 'rooms' ) > 0 AND
       SUM( value BETWEEN 40 AND 80 AND key = 'sqft' ) > 0 AND
       ......and so on.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...