2013-11-19 7 views
0

У меня есть запрос, как этогоMysql - полнотекстовый поиск - сопоставить значение в где?

SELECT id, search, MATCH(search) AGAINST('+iron +maiden') m FROM mp3 WHERE MATCH(search) AGAINST('+iron +maiden') ORDER BY m DESC; 

отлично работает, результаты сортируются, Everythings хорошо. Затем я попытался ограничить мои результаты лучшими матчи. Я заметил м является STH между 4 и 20 (не всегда), так я подумал:

SELECT id, search, MATCH(search) AGAINST('+iron +maiden') m FROM mp3 WHERE m > 10 AND MATCH (search) AGAINST ('+iron +maiden') ORDER BY m DESC; 

Bam! ОШИБКА 1054 (42S22): Неизвестный столбец «м» в «где предложение»

Теперь я знаю, что это не будет работать, но я не знаю, почему, может быть, я устал или что-то ... Поэтому я хотел бы спросить вас:

  1. Почему это не сработало?
  2. Есть ли аналогичное рабочее решение? (SQL только, я знаю, что я могу фильтровать результаты позже)

Приветствия

EDIT Итак, как @alko предложил я сделал некоторые бенчмаркинг и это выглядит многообещающе:

Match against within inner select (without WHERE m > 10 so resultset is identical as in match against below): 
SELECT id, search, m FROM (SELECT id, search, MATCH(search) AGAINST('+metallica') m FROM mp3 WHERE MATCH(search) AGAINST('+metallica')) matched_mp3 ORDER BY m DESC; 
2818 rows in set (0.03 sec) 
SELECT id, search, m FROM (SELECT id, search, MATCH(search) AGAINST('+dead +weather') m FROM mp3 WHERE MATCH(search) AGAINST('+dead +weather')) matched_mp3 ORDER BY m DESC; 
6968 rows in set (0.10 sec) 
SELECT id, search, m FROM (SELECT id, search, MATCH(search) AGAINST('+led +zeppelin') m FROM mp3 WHERE MATCH(search) AGAINST('+led +zeppelin')) matched_mp3 ORDER BY m DESC; 
1381 rows in set (0.02 sec) 
SELECT id, search, m FROM (SELECT id, search, MATCH(search) AGAINST('+lana +del +ray +paradise') m FROM mp3 WHERE MATCH(search) AGAINST('+lana +del +ray +paradise')) matched_mp3 ORDER BY m DESC; 
7447 rows in set (0.11 sec) 

Match against: 
SELECT id, search, MATCH(search) AGAINST('+metallica') m FROM mp3 WHERE MATCH(search) AGAINST('+metallica') ORDER BY m DESC; 
2818 rows in set (0.03 sec) 
SELECT id, search, MATCH(search) AGAINST('+dead +weather') m FROM mp3 WHERE MATCH(search) AGAINST('+dead +weather') ORDER BY m DESC; 
6968 rows in set (0.10 sec) 
SELECT id, search, MATCH(search) AGAINST('+led +zeppelin') m FROM mp3 WHERE MATCH(search) AGAINST('+led +zeppelin') ORDER BY m DESC; 
1381 rows in set (0.01 sec) 
SELECT id, search, MATCH(search) AGAINST('+lana +del +ray +paradise') m FROM mp3 WHERE MATCH(search) AGAINST('+lana +del +ray +paradise') ORDER BY m DESC; 
7447 rows in set (0.12 sec) 

Match against within inner select (with WHERE m > 10) 
SELECT id, search, m FROM (SELECT id, search, MATCH(search) AGAINST('+metallica') m FROM mp3 WHERE MATCH(search) AGAINST('+metallica')) matched_mp3 WHERE m > 10 ORDER BY m DESC; 
8 rows in set (0.02 sec) 
SELECT id, search, m FROM (SELECT id, search, MATCH(search) AGAINST('+dead +weather') m FROM mp3 WHERE MATCH(search) AGAINST('+dead +weather')) matched_mp3 WHERE m > 10 ORDER BY m DESC; 
46 rows in set (0.08 sec) 
SELECT id, search, m FROM (SELECT id, search, MATCH(search) AGAINST('+led +zeppelin') m FROM mp3 WHERE MATCH(search) AGAINST('+led +zeppelin')) matched_mp3 WHERE m > 10 ORDER BY m DESC; 
1070 rows in set (0.01 sec) 
SELECT id, search, m FROM (SELECT id, search, MATCH(search) AGAINST('+lana +del +ray +paradise') m FROM mp3 WHERE MATCH(search) AGAINST('+lana +del +ray +paradise')) matched_mp3 WHERE m > 10 ORDER BY m DESC; 
532 rows in set (0.06 sec) 

ответ

1

Это обыкновение независимо от полнотекстового поиска, например,

select concat(name, ' ', surname) as full_name 
    from user 
where full_name = 'john smith' 

закончится с той же ошибкой. Причина в том, что select оценивается до пункта where. Следовательно, когда условие where оценивается, не существует никаких псевдонимов. Вероятно, самым простым способом является обертывание с помощью внутреннего выбора:

SELECT * 
    FROM (SELECT id, 
       search, 
       MATCH(search) AGAINST('+iron +maiden') m 
     FROM mp3) matched_mp3 
    WHERE m > 10 
    ORDER BY m DESC; 
+0

Хорошо, это довольно простое решение. Мне интересно об этом. У меня около 1200 тыс. Записей ... Хорошо, когда я писал это, я заметил, что моя консоль mysql открыта, поэтому я сделал быстрый тест. Нормальный выбор (1-й из моего поста) для (+ + истребителей +): 2222 строки в наборе (0,06 сек); внутренний выбор, как указано выше: 262 строки в наборе (7.98 сек). Так что это довольно медленно – f1ames

+0

@ f1ames, во-первых, вы должны сравнить sqls, возвращающие одинаковые наборы данных, или это несправедливое сравнение. И я забыл 'где match (...)' часть для внутреннего запроса, вы включили это? Во-вторых, это вопрос анализатора/плана exec. Для oracle db я уверен, что sqls будут выполнены одинаково. Не так много разбираюсь в анализе mysql. – alko

+0

Хорошо, я думаю, что основная причина была я не заметил, ГДЕ во внутреннем выборе отсутствует: D Взгляните на мое сообщение и время запроса. Он показывает, что вы, вероятно, правы в равных исполнениях этих двух типов запросов. – f1ames

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