Sql-запрос с несколькими операторами
У меня есть для меня довольно сложный запрос mysql, на котором я полностью застрял и не могу найти ответ для онлайн.
Здесь мой запрос:
SELECT
items.*
FROM
items
INNER JOIN
items_meta_data
WHERE
(
(meta_key = 'lat' AND meta_value >= '55')
OR
(meta_key = 'lat' AND meta_value <= '65')
)
AND
(
(meta_key = 'long' AND meta_value >= '20')
OR
(meta_key = 'long' AND meta_value <= '30')
)
GROUP BY
item_id
Конечно, я тестировал запрос только с 1-м выражением, и это работает нормально. Поэтому, если я передаю только длинную или лат-часть, я получаю результаты. Только когда я пытаюсь сшить их вместе, я получаю разные результаты.
Спасибо за помощь заранее!
Структура таблицы выглядит следующим образом:
Элементы таблицы:
Я БЫ
название предмета
ITEM_DESCRIPTION
Таблица мета:
meta_id
item_id
meta_key
meta_value
Решение
Кому интересно, мне наконец удалось решить эту проблему. Спасибо всем за вашу помощь и внутренности.
SELECT
SQL_CALC_FOUND_ROWS items.*
FROM
items
INNER JOIN
items_meta ON (items.ID = items_meta.post_id)
INNER JOIN
items_meta AS m1 ON (items.ID = m1.post_id)
WHERE
1=1
AND
items.post_type = 'post'
AND
(items.post_status = 'publish')
AND
( (items_meta.meta_key = 'lat' AND CAST(items_meta.meta_value AS SIGNED) BETWEEN '55' AND '65')
AND
(m1.meta_key = 'long' AND CAST(m1.meta_value AS SIGNED) BETWEEN '20' AND '30') )
GROUP BY
items.ID
ORDER BY
items.date
DESC
Ответы
Ответ 1
Вы должны учитывать, что GROUP BY
происходит после того, как условия предложения WHERE
были оценены. А предложение WHERE
всегда учитывает только одну строку, что означает, что в вашем запросе условия meta_key
всегда будут препятствовать выбору любых записей, так как один столбец не может иметь несколько значений для одной строки.
А как насчет избыточных проверок meta_value? Если значение разрешено быть как меньшим, так и большим, чем заданное значение, то его фактическое значение вообще не имеет значения - проверка может быть опущена.
Согласно одному из ваших комментариев, вы хотите проверить места, расположенные на некотором расстоянии от определенного места. Чтобы получить правильные расстояния, вам действительно нужно использовать какую-то правильную функцию расстояния (см., Например, этот вопрос). Но этот SQL должен дать вам представление о том, как начать:
SELECT items.* FROM items i, meta_data m1, meta_data m2
WHERE i.item_id = m1.item_id and i.item_id = m2.item_id
AND m1.meta_key = 'lat' AND m1.meta_value >= 55 AND m1.meta_value <= 65
AND m2.meta_key = 'lng' AND m2.meta_value >= 20 AND m2.meta_value <= 30
Ответ 2
Это..
(
(meta_key = 'lat' AND meta_value >= '60.23457047672217')
OR
(meta_key = 'lat' AND meta_value <= '60.23457047672217')
)
совпадает с
(
(meta_key = 'lat')
)
Объединяя все вместе (то же самое относится к фильтру long
), у вас есть это невозможное предложение WHERE, которое не даст строк, потому что meta_key
не может быть 2 значения в одной строке
WHERE
(meta_key = 'lat' AND meta_key = 'long' )
Вам необходимо просмотреть своих операторов, чтобы убедиться, что вы правильно поняли
Ответ 3
Что такое meta_key
? Разделите все условия meta_value
, уменьшите, и в итоге получится следующее:
SELECT
*
FROM
meta_data
WHERE
(
(meta_key = 'lat')
)
AND
(
(meta_key = 'long')
)
GROUP BY
item_id
Так как meta_key
никогда не может одновременно равняться двум различным значениям, результаты не возвращаются.
Основываясь на комментариях по всему этому вопросу и ответам до сих пор, похоже, что вы ищете что-то большее в соответствии с этим:
SELECT
*
FROM
meta_data
WHERE
(
(meta_key = 'lat')
AND
(
(meta_value >= '60.23457047672217')
OR
(meta_value <= '60.23457047672217')
)
)
OR
(
(meta_key = 'long')
AND
(
(meta_value >= '24.879140853881836')
OR
(meta_value <= '24.879140853881836')
)
)
GROUP BY
item_id
Обратите внимание на OR
между условиями верхнего уровня. Это связано с тем, что вам нужны записи lat
или long
, поскольку ни одна запись никогда не будет lat
и long
.
Я все еще не уверен, что вы пытаетесь выполнить с помощью внутренних условий. Любое ненулевое значение будет соответствовать этим числам. Так что, может быть, вы сможете уточнить, что вы пытаетесь сделать там. Я также не уверен в цели предложения GROUP BY
, но это может быть вне контекста этого вопроса.
Ответ 4
Можно ли увидеть структуру вашей таблицы? Если я это понимаю, то предположение, сделанное запросом, состоит в том, что запись может быть только meta_key - 'lat'
или meta_key = 'long'
не потому, что каждая строка имеет только один столбец meta_key
и может содержать только одно соответствующее значение, а не 2. Это объясняет, почему вы не получаете результаты при подключении с помощью AND
; это невозможно.