2011-12-27 3 views
26

У меня для меня довольно сложный запрос mysql, на котором я полностью застрял и не могу найти ответ для онлайн.sql query with multiple where statements

Вот мой запрос:

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 заявление и что работает отлично. Поэтому, если я передаю только длинную или лат-часть, я получаю результаты. Только когда я пытаюсь сшить их вместе, я получаю разные результаты.

Спасибо за помощь заранее!

Структура таблицы выглядит следующим образом:

Таблица пунктов: ID item_name 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

Можете ли вы конкретно уточнить, что происходит, когда вы «сшиваете их вместе»? Как выглядят данные, которые вы запрашиваете, и какие результаты вы получаете? – David

+1

Мы можем предположить, что это не ошибка в mysql, поэтому вам нужно сказать, чего вы ожидали, и то, что вы заметили. Какие данные вы вводите в запрос? – tenfour

+2

Вы ищете строку базы данных, где 'meta_key' - это' 'lat'' и' 'long''. Я не уверен, что это возможно ... – lonesomeday

ответ

18

Вы должны учитывать, что GROUP BY происходит после того, как условия условия WHERE были оценены. И в предложении WHERE всегда учитывается только одна строка, что означает, что в вашем запросе условия meta_key всегда будут препятствовать выбору любых записей, поскольку один столбец не может иметь несколько значений для одной строки.

А как насчет избыточных проверок meta_value? Если значение допускается как меньшим, так и большим, чем заданное значение, то его фактическое значение вообще не имеет значения - проверка может быть опущена.

Согласно одному из ваших комментариев, вы хотите проверить места на расстоянии, не превышающем определенное расстояние от данного места. Чтобы получить правильные расстояния, вам действительно нужно использовать какую-то правильную функцию расстояния (см., Например, this question). Но этот 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 
+0

Это, вероятно, где моя ошибка лежит. Мне нужно найти предметы на расстоянии около 10 км от текущего места. Для тестирования я добавил в запрос текущие координаты. Они должны быть на 5 км меньше, чем текущее местоположение, и на 5 км больше, чем текущее местоположение. – user1117774

+0

Ааа, это просветительская. Но почему тогда сравнивать два раза с одинаковым значением? То, что вам понадобится, - это двойное соединение, один раз для lng и один раз для значения lat, я попытаюсь использовать его в своем ответе. – codeling

+0

Да, я так испорчен после битвы с этим в течение нескольких часов, что мне трудно объяснить. Спасибо за ваше терпение! Я изменил свой первоначальный почтовый запрос, чтобы больше соответствовать тому, что мне нужно ... Я отредактирую его немного больше, чтобы получить более полное представление. – user1117774

3

Это ..

(
     (meta_key = 'lat' AND meta_value >= '60.23457047672217') 
    OR 
     (meta_key = 'lat' AND meta_value <= '60.23457047672217') 
) 

такая же, как

(
     (meta_key = 'lat') 
) 

Добавление все это вместе (то же самое относится и к long фильтра) у вас есть это невозможно ИНЕКЕ, который даст нет строк, потому что meta_key не может быть 2 значения в одной строке

WHERE 
    (meta_key = 'lat' AND meta_key = 'long') 

Вы должны пересмотреть свои операторы, чтобы убедиться, что вы получите правильную логику

+0

Это неправда. Каждый элемент имеет несколько метаданных в мета-таблице. Поэтому я ищу элементы, которые соответствуют нескольким совпадениям. – user1117774

+0

@ пользователь1117774: есть. это правда. Логика диктует ваше WHERE неправильное – gbn

+0

Каждый элемент в элементах таблицы имеет несколько строк метаданных, прикрепленных к нему из мета-таблицы. Например, элемент с ID = 1 имеет в мета таблице следующие строки: rowID = 1, itemID = 1, meta_key = lat, meta_value = '1234' rowID = 2, itemID = 1, meta_ket = long, meta_valye = '5678' – user1117774

0

Что такое 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, но это может быть вне контекста этого вопроса.

+0

Существует несколько строк с метаданными на элемент ... – user1117774

+0

@ user1117774: Но ни одна строка не будет соответствовать этому запросу. Может быть, вы хотите, чтобы 'AND' в сокращенной версии был' OR'?Обновите вопрос с помощью структуры таблицы, и мы можем помочь построить запрос. – David

+0

Запрос должен соответствовать двум строкам из мета-таблицы для каждого элемента, чтобы быть действительно действительным. – user1117774

0

Можем ли мы увидеть структуру вашего стола? Если я это понимаю, то предположение, сделанное запросом, состоит в том, что запись может быть только meta_key - 'lat' или meta_key = 'long' не потому, что каждая строка содержит только один столбец meta_key и может содержать только одно соответствующее значение, а не 2. Это объясняет, почему вы Получать результаты при подключении с помощью AND; это невозможно.

+0

Я добавил краткое описание структуры таблицы в первом сообщении. Я должен был сделать это раньше, спасибо, что упомянул это. – user1117774