SELECT LIKE и %

hex

Новичок
SELECT LIKE и %

Есть таблица в которой есть поле
text (текстовое поле)
а также есть форма в которой среди прочего есть текстовое поле
txt (т.е. $txt)

Задача такая - нужно чтобы при поиске сравнивались значения $txt с полем text
и если совпадение есть то выдавался результат что "совпадения есть" (это все реализовано через mysql_numrows не в этом вопрос) а если нет то соответственно...
Вообщем запрос такой:

SELECT text from table WHERE text LIKE '%".$txt."%' ORDER BY id DESC

Все работает но ...
скажем переменная $txt = "privet"
и в базе есть такое слово, тогда результат есть. Это нормально.
Но вот потом вводим в текстовое поле "pr" ($txt = "pr"), также выдает что есть совпадения.
Я понимаю что это % работают, но вот мне нужно
чтобы искалось именно "privet", а не "pr", "pri" или "p". Кроме того, нужно чтобы и в слове "privetmedved" также было совпадение. Как быть? Я конечно менял и так и сяк, но не удолетворяет результат моим условиям.
Неужели в регулярки лезть :(?

и кстати если в строке два слова privet medved то НЕ выдает совпадений. Выдает только если слово одно. Так что наверное нужно как то со строкой работать? Разбивать на слова что ли? Как это сделать (если здесь собака зарыта). Тоже регулярные выражения? Или есть способ проще?

Т.е. либо с запросом что то делать либо со строкой. Подскажите как лучше?

-~{}~ 04.08.06 20:32:

Так вот обратил внимание на
str_word_count
Извините наверное офтоп здесь уже получается. Но может и с mysql запросом можно что то сделать?
 

denver

?>Скриптер
ничего не понятно.. тебе нужно чтобы по
"privet" искалось "... privet medved.." и "... privetmedved.."
но не нужно чтобы по "pri" находилось то же самое?
а какая логика? pri, pr, p слишком короткое слова? Какой бы ты регуляркой решил это, хоть примерно?
 

hex

Новичок
Автор оригинала: denver
ничего не понятно.. тебе нужно чтобы по
"privet" искалось "... privet medved.." и "... privetmedved.."
но не нужно чтобы по "pri" находилось то же самое?
а какая логика? pri, pr, p слишком короткое слова? Какой бы ты регуляркой решил это, хоть примерно?
Совершенно верно. Именно так и нужно. Нужно для фильтра спама. Нужно чтобы только "viagra" искалась но не "via" "vi". Со строкой то я разобрался. Вот так сделал чтобы ее порезать на отдельные слова (правда корректно работает только на английском, но мне в принципе этого хватит):

PHP:
$skolko=str_word_count ($txt); //счетчик того сколько слов всего
 $trio=str_word_count ($txt,1); //собственно разбивка на слова
//ну и затем цикл дл вывода слов в массив
 for ($i=0;$i<=$skolko-1;$i++) {
 $dun[$i]=$trio[$i];
 echo ($trio[$i]); echo "<br>";
//ну и проверка есть ли такие слова в базе 
$anti=mysql_query("SELECT text from antispamcomment WHERE text LIKE '%".$dun[$i]."%' ORDER BY id DESC");
 $antisp = mysql_numrows($anti);
 $antispam = $antispam + $antisp;//ну и если есть то плюсуются сюда, а потом я условие задам что если здесь
//больше нуля то "фиг вам"
     }
Проблема осталась какая то пустяковая (просто уже торможу капитально, устал). Нужно чтобы искалось только слово целиком. Ставлю = не ищет, ставлю LIKE без % тоже не ищет слово. Понимаю что затупил. Подскажите!

-~{}~ 04.08.06 23:16:

Все таки вычислил я ошибку (вот млин как холодильник тупо смотрел и не видел)

Я писал чтобы строгое соответствие найти

PHP:
SELECT text from antispamcomment WHERE text LIKE ".$dun[$i]." ORDER BY id DESC"
но когда убирал % убрал и ' (апосты) вот и не получалось ничего
Когда написал правильно

PHP:
SELECT text from antispamcomment WHERE text LIKE '".$dun[$i]."' ORDER BY id DESC
Все получилось. Ну теперь спамеры держитесь :) :) :)
а то честное слово достали виагры всякие :) (извините за оффтоп)
 

denver

?>Скриптер
К чему такие муки и столько запросов. Задай спам слова массивом. А при проверке поста проверяй не каждое слово сообщения, а наличие хотя б одного спамслова из массива (вот этот массив и перебирай). И в этот массив спам-слов уже добавляй что хочешь, хочешь viagra а хоть и vi.
 

hex

Новичок
а я так и делаю
в базу так и добавляю
а затем массив из введенных слов сверяю с тем что в базе есть.
А что по коду не видно?
 

denver

?>Скриптер
ЗЫ. не называй так переменные... это по-зверски даже для себя.
 

hex

Новичок
Или ты имеешь ввиду перед этим скачивать из базы в массив а затем сверять массивы?
 

hex

Новичок
Автор оригинала: denver
ЗЫ. не называй так переменные... это по-зверски даже для себя.
Озвереешь тут когда как (хотя наверное слово как и лишнее... :)) тупой просидел два часа над апостофом. :)
 

denver

?>Скриптер
Автор оригинала: hex
Или ты имеешь ввиду перед этим скачивать из базы в массив а затем сверять массивы?
Ну это уж стопудов лучше чем столько запросов. Если спамслов всего максимум 100-200. А то и тыща.
 

hex

Новичок
Автор оригинала: denver
Ну это уж стопудов лучше чем столько запросов. Если спамслов всего максимум 100-200. А то и тыща.
Вообще то ты прав. Наверное так и сделаю. А то буду базу так в цикле напрягать. Не порядок это.

-~{}~ 04.08.06 23:27:

Кстати о птичках (опять прошу извинения, но вотуж как говорят к слову) а как массив не с нуля начать? Просто нужно было один раз.
 

denver

?>Скриптер
а затем массив из введенных слов сверяю с тем что в базе есть.
По ходу я как раз про наоборот говорю. Проверять есть ли хоть одно спам слово (из массива) в тексте. Вместо того чтобы проверять есть ли хоть одно слово из текста в спам-листе.
Как минимум так легче впоследствии если придется проверять по регвыражениям .

-~{}~ 04.08.06 23:32:

Кстати о птичках (опять прошу извинения, но вотуж как говорят к слову) а как массив не с нуля начать? Просто нужно было один раз.
http://php.net/manual/ru/language.types.array.php
 

hex

Новичок
Автор оригинала: denver
По ходу я как раз про наоборот говорю. Проверять есть ли хоть одно спам слово (из массива) в тексте. Вместо того чтобы проверять есть ли хоть одно слово из текста в спам-листе.
Как минимум так легче впоследствии если придется проверять по регвыражениям .
Но ведь массив в базе и тогда его все равно придется из бызы циклом вытягивать. Тогда уже два цикла получится. Так что все же мой вариант по меньше будет. Или опять туплю?

-~{}~ 04.08.06 23:35:

А за ссылку спасибо!
 

denver

?>Скриптер
Опс. я только понял что таблица antispamcomment это таблица спам слов... Название говорящее...

Выгребай из нее всё одним запросом "SELECT text FROM antispamcomment" и потом (while mysql_fetch...) проверяй каждое слово на наличие в посте.

-~{}~ 04.08.06 23:41:

ЗЫ. Поправился... перечитай этот пост еще раз ;)
 

hex

Новичок
А есть разница (по напряжению базы)
между
while ... mysql_fetch_array - перебор массива десять раз

и
десятью селектами???
 

denver

?>Скриптер
mysql_fetch_array не грузит базу. Потому что не делает SQL запросов. Просто считывает строки которые были уже отобраны ранее функцией mysql_query().
 

hex

Новичок
Теперь все очевидно. Сделаю так. Спасибо!

-~{}~ 05.08.06 00:04:

Хотя все же такой вопросик.
Вот например я длину комментария (который и буду на спам проверять) установил скажем в 500 символов. Т.е. в среднем сто слов где то. А вот в базе у меня может скопиться с тысячу вариантов. И будет делаться большая выборка. а затем эта тысяча выбранная еще и напрягать php сверяясь. Все же...
 

denver

?>Скриптер
Что быстрее 100 SQL c LIKE или 1 SQL без условий вообще но с проверками в PHP? Если не убедительно то несложно и эксперимент провести - засеки microtime() и проверь как будет быстрее. Так даже правильно, вдруг я ошбаюсь и именно тут твой способ лучше.
 

hex

Новичок
Спасибо! Проверю на досуге.
Неплохо получилось! Из одного топа столько полезных вещей получил!
Еще раз благодарю и респект!

-~{}~ 06.08.06 22:20:

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

В качестве "приза" для таких же чайников как и я, я выношу итоговый код спам фильтра который у меня получился. Я старался написать пояснения по коду для самым самых начинающих. Обратите внимание как модифицировался MySQL запрос. Он сократился донельзя, став самым простым. А также он теперь только один вместо десятков, а может сотен в старом варианте (посмотрите посты выше, там есть промежуточный код).

Вообщем мое творчество :) (хотелось бы чтобы Фанат или denver покритиковали, - может еще проще можно сделать)

PHP:
//Запрос спам выражений которые у нас в базе есть
  $querry=mysql_query("SELECT text from antispamcomment");//в таблице antispamcomment
  //есть текстовое поле text в котороевносятся спам выражения. Вот эти выражения и выбираем.
  
  echo mysql_error(); //если какие то проблемы запросом mysql_query то выдает ошибку, если нет ничего не выдает

         $checkformtext = strtolower($txt); //здесь мы с помощью функции strtolower() просто переводим все
         // что у нас написано в текстовом поле формы (имя этого поля в форме - txt, посему у нас и переменная $txt)
         // в нижний регистр (чтобы корректно сравнивать потом строки)


   //цикл извлечения спам выражений из базы
   //с помощью массива получаемого с помощью функции mysql_fetch_array
   while ($row = mysql_fetch_array($querry)) {
   
          $spamblockrow = strtolower($row['text']);//соответственно и здесь мы с помощью функции strtolower()
          //переводим все спам выражения которые у нас есть в таблице antispamcomment также в нижний регистр
         // (чтобы опять же корректно сравнивать потом строки)

        $substr_count = substr_count($checkformtext,$spamblockrow);//Интереснейшая строковая функция substr_count()
        // котораяи находит количество вхождений фрагмента (в нашем случае это одно из спам выражений из таблицы
        // antispamcomment) в строку (т.е. то что в текстовое поле формы ввели).
        //Вообщем функция substr_count() именно то что нужно для спам фильтра!


         $antispam = $antispam + $substr_count;//счетчик. Просто суммирует количество вхождений.
         //Далее обрабатывается так: если он равен нулю (т.е. не найдено ни одного совпадения с выражениями
         // из  спам базы) то можно вставлять комментарий в базу, а если нет то отменить. Вот и спам фильтр.

         //ПРИЧЕМ ОСОБЕННОСТИ ДАННОГО ФИЛЬТРА В ТОМ, ЧТО ОН МОЖЕТ ИСКАТЬ ОЧЕНЬ БОЛЬШИЕ СЛОЖНЫЕ СТРОКИ
         //А НЕ ПРОСТО СЛОВА ОДИНОЧНЫЕ (А ЭТО ДЛЯ ФИЛЬТРОВ ВАЖНО).
         // КРОМЕ ТОГО ЭТОТ ФИЛЬТР ОТЛИЧНО РАБОТАЕТ С РУССКИМ ЯЗЫКОМ
         // (КОНЕЧНО КОДИРОВКИ В БАЗЕ НУЖНО СМОТРЕТЬ).
         
        }

echo "Совпадений выдало - $antisp Счетчик = $antispam"; echo "<br>";  // просто это для проверки сколько
//вхождений найдено. Эту строку нужно заремарить потом
 

denver

?>Скриптер
hex
Молодец, неплохо разобрался :)

ЗЫ. Если тебе одного совпадения достаточно, то можно выходить из цикла командой break чтобы сократить количество проверок.
 
Сверху