2012-03-16 4 views
4

У моего делового партнера и у меня возникают проблемы с выбором из представления MySQL, в котором есть предложение HAVING.SELECT from MySQL View С предложением HAVING возвращает пустой набор результатов

Запрос просто выбирает несколько полей из представления, динамически определяет расстояние с несколькими вычислениями и псевдонизирует его как «расстояние» - затем ограничивает результаты теми строками с расстоянием, меньшим, чем поставляемая переменная.

Расстояние вычисляется по формуле Haversine, на который ссылается Google Maps: https://developers.google.com/maps/articles/phpsqlsearch

Вот что я знаю:

1) Когда HAVING пункт удаляется из запроса, он возвращает все результаты в представлении успешно, , включая рассчитанное «расстояние» для каждой строки

2) Когда к запросу добавляется предложение HAVING, оно возвращает пустой r esult набор

3) Мы также пытались замены переменной в HAVING предложении к статическому числа - это также возвращается пустой результирующий набор

содержимое этого зрения, кажется, не имеет значения, так как все работает без HAVING пункта.

Вот запрос:

SELECT 
restaurantName, 
restaurantID, 
locationID, 
locationCity, 
locationState, 
locationAddress, 
locationLatitude, 
locationLongitude, 
(3959 * acos(cos(radians('%s')) * cos(radians(locationLatitude)) * cos(radians(locationLongitude) - radians('%s')) + sin(radians('%s')) * sin(radians(locationLatitude)))) AS distance 
FROM newView 
HAVING distance < '%s' 
ORDER BY distance 

Помните, что вид вычисляет «расстояние» для каждой выбранной строки отлично без HAVING пункта, поэтому мы убеждены, что проблема лежит там ... когда мы вынимайте его, все работает, но возвращается каждая строка в представлении.

Любые идеи, почему предложение HAVING возвращает пустой набор? Является ли предложение HAVING несовместимым с представлениями?

ответ

2

Попробуйте это:

select * from (
    SELECT 
    restaurantName, 
    restaurantID, 
    locationID, 
    locationCity, 
    locationState, 
    locationAddress, 
    locationLatitude, 
    locationLongitude, 
    (3959 * acos(cos(radians('%s')) * cos(radians(locationLatitude)) * cos(radians(locationLongitude) - radians('%s')) + sin(radians('%s')) * sin(radians(locationLatitude)))) AS distance 
    FROM newView 
) S 
where distance < '%s' 
ORDER BY distance 
+1

Спасибо за ваш ответ. Я использовал идею здесь (производную таблицу) с предложением HAVING вместо предложения where, и теперь он работает отлично. Большое спасибо. –

2

Предложение HAVING предназначено для использования при агрегированных данных при группировке строк вместе с использованием предложения GROUP BY. Поскольку вы работаете в каждой строке отдельно, вы должны заменить HAVING на пункт WHERE. См. this example.

Использование HAVING в неагрегатных столбцах в вашем списке SELECT является нестандартным поведением, поддерживаемым MySQL, но поведением, на которое не следует полагаться. Даже MySQL reference обескураживает это:

Не используйте HAVING для элементов, которые должны находиться в предложении WHERE. Для например, не пишут следующее:

SELECT col_name FROM tbl_name HAVING col_name > 0;

Записать это вместо:

SELECT col_name FROM tbl_name WHERE col_name > 0;

Как и в сторону: если вы передаете аргументы от пользователя к вашему запросу (с %s), убедитесь, что вы смотрите в подготовленные заявления. В противном случае у вас может быть вопиющий недостаток безопасности на ваших руках.

+0

Спасибо за ваш ответ, но это не правильно. Предложение HAVING также может использоваться с совокупными функциями, которые не сгруппированы, что мы имеем в нашем примере - «расстояние». Когда мы не использовали представление, у нас был этот точный запрос, и он работал как предполагалось, за исключением того факта, что нам понадобилось представление для упрощения запроса. Ознакомьтесь с документацией Google, с которой я связан в вопросе, и вы увидите, как они используют предложение HAVING, чтобы ограничить «расстояние» - это вычисленное поле. –

+0

Я попытался заменить HAVING WHERE и вместо получения пустого набора результатов получил ошибку MySQL. Вот запрос от Google из документации выше: 'ВЫБРАТЬ идентификатор, (3959 * ACOS (Cos (радиан (37)) * Cos (радианы (лат)) * Cos (радианы (LNG) - радиан (- 122)) + sin (радианы (37)) * sin (радианы (лат)))) AS расстояние От маркеров HAVING расстояние <25 ORDER BY расстояние LIMIT 0, 20; ' –

+0

Использование' HAVING' таким образом это нестандартное поведение, поддерживаемое MySQL, но поведение, на которое я бы не опирался. «Не используйте HAVING для элементов, которые должны быть в ИНЕКЕ, например, не написать следующее: ' ВЫБРАТЬ col_name FROM имя_таблицы HAVING имя_столбца> 0; ' Write вместо этого:. ' ВЫБОР col_name FROM tbl_name WHERE col_name> 0; '" ([источник] (http://dev.mysql.com/doc/refman/5.6/en/select.html)) Обратите также внимание, что в вашем примере нет агрегированных функций , Тригонометрические функции, используемые для вычисления расстояния, работают на столбцах одной строки. – AerandiR

Смежные вопросы