Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > СУБД, общие вопросы > Помогите оптимизировать запрос :)


Автор: Wowa 24.9.2005, 14:19
Помогите оптимизировать запрос smile

Код

SELECT * FROM table
WHERE 
group1 LIKE '%железо%' OR group1 LIKE '%газ%' OR group1 LIKE '%метан%' OR group1 LIKE '%вода%' AND
(group2 LIKE '%железо%' OR group2 LIKE '%газ%' OR group2 LIKE '%метан%' OR group2 LIKE '%вода%' OR group2 IS NULL) AND
(group3 LIKE '%железо%' OR group3 LIKE '%газ%' OR group3 LIKE '%метан%' OR group3 LIKE '%вода%' OR group3 IS NULL)


Поля group1, group2, group3 - имеют тип TEXT.

Нужно, чтобы были найден все записи, если:
- хотя бы одно из ключевых слов присутствует в group1, но group2 и group3 - не заполнены.
- хотя бы одно из ключевых слов присутствует в group1 и хотя бы одно group2, но group3 - пустой поле.
- хотя бы одно из ключевых слов присутствует в group1, хотя бы одно group2 и хотя бы одно в group3

Автор: Akina 24.9.2005, 23:40
Цитата(Wowa @ 24.9.2005, 15:19)
Нужно, чтобы были найден все записи, если:

А если ни одно из этих трех условий не выполняется, то можно и не искать все записи? во блин...

Ты чего, сильно спешишь? сформулируй нормально. а лучше ДЛЯ СЕБЯ нарисуй блок-схему проверки условий - глядишь, и проще станет. толко рисуй непременно в бумаге и карандашом. Мне ЭТО часто помогало.

Автор: igon 25.9.2005, 00:40
1.Т.к. для выражения типа <условие1>OR<условие2>OR<условие3>OR... <условие2> и последующие не анализируется, если <условие1> верно, предпочтительнее будет
Код

SELECT * FROM table
WHERE 
group1 LIKE '%железо%' OR group1 LIKE '%газ%' OR group1 LIKE '%метан%' OR group1 LIKE '%вода%' AND
(group2 IS NULL OR group2 LIKE '%железо%' OR group2 LIKE '%газ%' OR group2 LIKE '%метан%' OR group2 LIKE '%вода%') AND
(group3 IS NULL OR group3 LIKE '%железо%' OR group3 LIKE '%газ%' OR group3 LIKE '%метан%' OR group3 LIKE '%вода%')

Кроме того, может помочь и анализ частоты встречаемости ключевых слов при формировании запроса: более частое дОлжно ставить на первое место.
2. Если база поддеживает DECODE(), то можно попробовать
Код

SELECT * FROM table
WHERE 
group1||DECODE(group2,NULL,'железо')||DECODE(group3,NULL,'железо') LIKE '%железо%' OR group1||DECODE(group2,NULL,'железо')||DECODE(group3,NULL,'железо') LIKE '%газ%' OR group1||DECODE(group2,NULL,'железо')||DECODE(group3,NULL,'железо') LIKE '%метан%' OR group1||DECODE(group2,NULL,'железо')||DECODE(group2,NULL,'железо') LIKE '%вода%' 

3. Если DECODE() не поддерживается, то
Код

SELECT * FROM table
WHERE 
(group1||group2||group3 LIKE '%железо%' OR 
 group1||group2||group3 LIKE '%газ%' OR  
 group1||group2||group3 LIKE '%метан%' OR 
 group1||group2||group3 LIKE '%вода%' ) OR
(group1 LIKE '%железо%' OR group1 LIKE '%газ%' OR group1 LIKE '%метан%' OR group1 LIKE '%вода%' AND (group2 IS NULL OR group3 IS NULL)) -- В постановке задачи не прописан, но учтен в Select вариант group1='железо', group2=null, group3='газ'. Или этого не может быть? Тогда 
...
(group2 IS NULL OR (group2 IS NOT NULL AND group3 IS NULL))

PS. Конкетенировать лучше через разделитель, скажем, пробел

Автор: Wowa 4.12.2005, 11:21
Цитата(igon @ 24.9.2005, 22:40)
В постановке задачи не прописан, но учтен в Select вариант group1='железо', group2=null, group3='газ'. Или этого не может быть? Тогда

Если в каком-то из столбцов вообще совпадение не найдено и этот столбец не пустой, то SELECT не должен находить эту строку.
Добавлено @ 11:22
Цитата(Akina @ 24.9.2005, 21:40)
А если ни одно из этих трех условий не выполняется, то можно и не искать все записи? во блин...

Если хотя бы одно условие не выполняется, то SELECT не должен извлекать эту строку из таблицы.
Добавлено @ 11:25
Цитата(igon @ 24.9.2005, 22:40)

SELECT * FROM table
WHERE
(group1||group2||group3 LIKE '%железо%' OR
group1||group2||group3 LIKE '%газ%' OR 
group1||group2||group3 LIKE '%метан%' OR
group1||group2||group3 LIKE '%вода%' ) OR
(group1 LIKE '%железо%' OR group1 LIKE '%газ%' OR group1 LIKE '%метан%' OR group1 LIKE '%вода%' AND (group2 IS NULL OR group3 IS NULL)) -- В постановке задачи не прописан, но учтен в Select вариант group1='железо', group2=null, group3='газ'. Или этого не может быть? Тогда
...
(group2 IS NULL OR (group2 IS NOT NULL AND group3 IS NULL))



Кстати..., насколько сложный/ресурсоемкий запрос у нас получился? В таблице около 1000 000 записей. Три столбца, в каждом примерно по 15 слов - с которыми нужно сравнение проводить.
Нужно находить все записи, не ограничивая их через LIMIT. Т.е. не частями, а сразу все..
Добавлено @ 11:25
база будет - MySQL использоваться.

Автор: Wowa 4.12.2005, 11:47
Ведь запрос:
Код

SELECT * FROM ibf_posts WHERE post LIKE "%PHP%"

гораздо более легкий, но выполняется на моем домашнем компе аж 40сек!

А такой запрос:
Код

SELECT * FROM ibf_posts WHERE post LIKE "%PHP%" LIMIT 1000

6сек.
Добавлено @ 11:49
Индекс правда отсутствует по столбцу post.
Добавлено @ 11:55
В общем... Похоже, что без LIMIT этот запрос офигенно ресурсоемкий

Автор: Wowa 4.12.2005, 14:53
У меня появилась другая идея решения этой задачи. Это создать на каждую группу слов по отдельной таблице.

group1
id|slovo

group2
id|slovo

group3
id|slovo



Код

SELECT * FROM group1, group2, group3 WHERE group1.id=group2.id=group3.id
    group1.slovo IN ('$slovo1', '$slovo2', '$slovo3') or group1.slovo IS NULL or
 or group2.slovo IN ('$slovo1', '$slovo2', '$slovo3') or group2.slovo IS NULL or
 or group3.slovo IN ('$slovo1', '$slovo2', '$slovo3') or group3.slovo IS NULL


Автор: Akina 4.12.2005, 22:07
Цитата(Wowa @ 24.9.2005, 15:19)
Нужно, чтобы были найден все записи, если:
- хотя бы одно из ключевых слов присутствует в group1, но group2 и group3 - не заполнены.
- хотя бы одно из ключевых слов присутствует в group1 и хотя бы одно group2, но group3 - пустой поле.
- хотя бы одно из ключевых слов присутствует в group1, хотя бы одно group2 и хотя бы одно в group3

Итак - независимо ни от чего хотя бы одно ключевое слово ОБЯЗАНО присуктствовать в поле group1. Если нет - запись не отбирается. Все остальное - дополнения к этому условию.
Посему кажется логичным реализовать вложенность - внутренний запрос отбирает те строки, в коих group1 содержит ключевое слово, а внешний запрос уже накладывает дополнительные условия.
Кроме того "group2 и group3 - не заполнены" - это частный случай "хотя бы одно group2, но group3 - пустой поле" (как я понял). Следовательно, первый вариант отбора можно вообще вычеркнуть - все что он отберет, отберет и второй вариант, а лишние проверки обработку не ускоряют.

Автор: Wowa 4.12.2005, 22:21
Цитата(Akina @ 4.12.2005, 20:07)
Следовательно, первый вариант отбора можно вообще вычеркнуть - все что он отберет, отберет и второй вариант, а лишние проверки обработку не ускоряют.

Второй вариант(group2) отберет, но он отберет больше, чем надо. Т.к. какое-то из слов должно встречаться также в group1, ну и в group3 - если оно заполнено.


Цитата(Akina @ 4.12.2005, 20:07)
Итак - независимо ни от чего хотя бы одно ключевое слово ОБЯЗАНО присуктствовать в поле group1. Если нет - запись не отбирается. Все остальное - дополнения к этому условию.

хотя бы одно из слов должно присутствовать во всех столбцах, если они не пусты.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)