|
|
|
Поиск не по NULL
|
|||
|---|---|---|---|
|
#18+
ASE 15 Сдаюсь. Как сделать поиск по нескольким реквизитам, если каждый раз требуется поиск только по части реквизитов, без дикой конструкции из IF'ов и чтобы не тормозило? т.е. Хочу чтобы один и тотже запрос отрабатывал только по не NULL'евым переменным, а NULL'евые игнорил, не искал по ним. Входящие данные ФИО Можно искать по Фамилии, Имени, Отчеству, как по всем сразу, так и по отдельности. Если указано Ф и О, а И = NULL, то по имени не ищется, а только по Ф и О и должны совпадать в одной записи все не NULL элементы. т.е. Ф = Иванов И = NULL О = Иванович Иванов Иван Иванович - есть Иванов Петр Иванович - есть и Иванов Иван Петрович - нету Петров Иван Иванович - нету Петров Иван Петрович - нету По одному параметру работает прекрасно и быстро: Код: plaintext 1. 2. Использование isnull(), case when end - вызывает тормоза запроса, хотя и позволяет сделать то что надо. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.09.2009, 14:22 |
|
||
|
Поиск не по NULL
|
|||
|---|---|---|---|
|
#18+
Не думаю что конструкция Код: plaintext Код: plaintext ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2009, 10:35 |
|
||
|
Поиск не по NULL
|
|||
|---|---|---|---|
|
#18+
golsa, вообще-то быстрее что тут думать, я практически проверял и к тому же мне НЕ нужны все записи из таблицы, если переменная равна NULL ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2009, 11:41 |
|
||
|
Поиск не по NULL
|
|||
|---|---|---|---|
|
#18+
Юзер3, А не проще ли оформить в виде процедуры которая вначале и разберет какой запрос конкретно выполнить ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2009, 12:41 |
|
||
|
Поиск не по NULL
|
|||
|---|---|---|---|
|
#18+
А если запользовать Like в следующей вариации: select * from Table where (LastName like '%' + IsNull(@LastName ,'') + '%') AND (Name like '%' + IsNull(@Name,'') + '%') AND (Patronymic like '%' + IsNull(@Patronymic,'') + '%') только проконтролируйте, чтобы IsNull возвращал именно пустую строку а не пробел ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2009, 12:50 |
|
||
|
Поиск не по NULL
|
|||
|---|---|---|---|
|
#18+
Sergey OrlovЮзер3, А не проще ли оформить в виде процедуры которая вначале и разберет какой запрос конкретно выполнить Вообще-то там 6 параметров, и они могут быть в любом сочетании, т.е. 36 вариантов селекта?.. %( ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2009, 12:58 |
|
||
|
Поиск не по NULL
|
|||
|---|---|---|---|
|
#18+
Mikle83 пишет: > А если запользовать Like в следующей вариации: > > select * from Table where > (LastName like '%' + IsNull(@LastName ,'') + '%') > AND (Name like '%' + IsNull(@Name,'') + '%') > AND (Patronymic like '%' + IsNull(@Patronymic,'') + '%') Этот запрос -- неоптимизируемый. Будет молотить всё таблицу, запись за записью. Posted via ActualForum NNTP Server 1.4 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2009, 13:05 |
|
||
|
Поиск не по NULL
|
|||
|---|---|---|---|
|
#18+
Юзер3 пишет: > Вообще-то там 6 параметров, и они могут быть в любом сочетании, т.е. 36 > вариантов селекта?.. %( Если ты хочешь, чтобы это всё быстро работало, тебе возможно даже ещё больше вариантов запроса придётся написать. Posted via ActualForum NNTP Server 1.4 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2009, 13:06 |
|
||
|
Поиск не по NULL
|
|||
|---|---|---|---|
|
#18+
Юзер3 пишет: > По одному параметру работает прекрасно и быстро: > > select * from Table where > LastName = @LastName and @LastName is not null > > но как добавить к этому остальные реквизиты не могу допереть... Первый совет, который хочется дать: 0) генерируй текст запроса на клиенте, так, чтобы он содержал только указанные критерии поиска. 1) не используй хранимые процедуры. Posted via ActualForum NNTP Server 1.4 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2009, 13:08 |
|
||
|
Поиск не по NULL
|
|||
|---|---|---|---|
|
#18+
Mikle83А если запользовать Like в следующей вариации: select * from Table where (LastName like '%' + IsNull(@LastName ,'') + '%') AND (Name like '%' + IsNull(@Name,'') + '%') AND (Patronymic like '%' + IsNull(@Patronymic,'') + '%') только проконтролируйте, чтобы IsNull возвращал именно пустую строку а не пробел Зачем мне Like, если я ищу конкретное значение? И тормозит это. Вот так работает как надо, только на большой таблице долго, индекс как раз по этим полям: Код: plaintext 1. 2. 3. 4. scan count 1, logical reads: (regular=576821 apf=323 total=577144), physical reads: (regular=0 apf=0 total=0), apf IOs used=0 Прямой запрос на фамилию соответственно: scan count 1, logical reads: (regular=80 apf=0 total=80), physical reads: (regular=5 apf=0 total=5), apf IOs used=0 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2009, 13:15 |
|
||
|
Поиск не по NULL
|
|||
|---|---|---|---|
|
#18+
MasterZiv Юзер3 пишет: > Вообще-то там 6 параметров, и они могут быть в любом сочетании, т.е. 36 > вариантов селекта?.. %( Если ты хочешь, чтобы это всё быстро работало, тебе возможно даже ещё больше вариантов запроса придётся написать. Да, ещё больше вариантов Варианты = 2 в степени число параметров Сделал такой страшный вид: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2009, 14:43 |
|
||
|
Поиск не по NULL
|
|||
|---|---|---|---|
|
#18+
Юзер3Входящие данные ФИО Можно искать по Фамилии, Имени, Отчеству, как по всем сразу, так и по отдельности. Если указано Ф и О, а И = NULL, то по имени не ищется, а только по Ф и О и должны совпадать в одной записи все не NULL элементы. IMHO Вам надо проработать саму постановку вопроса. Я лично сомневаюсь, что пользователь в большом списке людей может искать кого то не по фамилии, а только по имени или отчеству ... ибо в этом абсолютно нет никакого смысла для него - ну выведутся для него тысячи Александров - что с ними он будет делать дальше ? Если же Фамилия или ее первая часть есть всегда, тогда все проще - делайте индекс на поле Фамилии, а остальные условия добавляйте как (@Имя IS NULL OR @Имя = Имя) AND (@Отчество IS NULL OR @Отчество = Отчество) - работать будет быстро, так как по индексу поднимутся все однофамильцы (а не так уж много), а потом по фильтру отсеются по заданному имени или отчеству. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2009, 14:54 |
|
||
|
Поиск не по NULL
|
|||
|---|---|---|---|
|
#18+
ASCRUSIMHO Вам надо проработать саму постановку вопроса. Я лично сомневаюсь, что пользователь в большом списке людей может искать кого то не по фамилии, а только по имени или отчеству ... ибо в этом абсолютно нет никакого смысла для него - ну выведутся для него тысячи Александров - что с ними он будет делать дальше ? Если же Фамилия или ее первая часть есть всегда, тогда все проще - делайте индекс на поле Фамилии, а остальные условия добавляйте как (@Имя IS NULL OR @Имя = Имя) AND (@Отчество IS NULL OR @Отчество = Отчество) - работать будет быстро, так как по индексу поднимутся все однофамильцы (а не так уж много), а потом по фильтру отсеются по заданному имени или отчеству. Да не важно, сделал поиск по всем полям. К тому же в базе есть такие китайцы, у которых есть только имя, или только фамилия... Александров по имени врятли будут искать, а вот какого-нибудь Ю вполне возможно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2009, 15:05 |
|
||
|
Поиск не по NULL
|
|||
|---|---|---|---|
|
#18+
С like запрос хоть и медленный зато будет отрабатывать именно так как вы хотите :) Еще один вариант: select * from Table where ((LastName = @LastName) OR (@LastName is null)) AND ((Name = @Name) OR (@Name is null)) AND ((Patronymic = @Patronymic) OR (@Patronymic is null)) тогда у вас в случае если один из параметров Null - по нему соотв. условие ставиться не будет ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2009, 15:27 |
|
||
|
Поиск не по NULL
|
|||
|---|---|---|---|
|
#18+
Попробуй все же конструкцию Код: plaintext 1. 2. 3. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2009, 15:32 |
|
||
|
Поиск не по NULL
|
|||
|---|---|---|---|
|
#18+
Mikle83Еще один вариант: select * from Table where ((LastName = @LastName) OR (@LastName is null)) AND ((Name = @Name) OR (@Name is null)) AND ((Patronymic = @Patronymic) OR (@Patronymic is null)) Такой вариант уже был у меня самого, см. выше. golsaПопробуй все же конструкцию Код: plaintext 1. 2. 3. Пробовал - сотни тысяч физических и логических чтений... как и в варианте выше. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2009, 15:49 |
|
||
|
Поиск не по NULL
|
|||
|---|---|---|---|
|
#18+
Попробуйте генерировать текст запроса на клиенте и подставлять параметры в текст запроса явно а не через @variable. В этом случае, у асе есть шансы как-то оценить селективность всех трех составляющего ФИО и в зависимости от этого выбрать один из трех индексов. Если я не ошибаюсь, асе не умеет оценивать селективность подставляемых через переменную параметров в запрос или работает в этом случае не достаточно умно. Но и сама собой, в этом случае статистика по колонкам таблицы должны быть самая свежая. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2009, 16:34 |
|
||
|
Поиск не по NULL
|
|||
|---|---|---|---|
|
#18+
Юзер3 пишет: > Зачем мне Like, если я ищу конкретное значение? > И тормозит это. Если у тебя справа от LIKE будт конкретное значение, то это всё равно, что = > > Вот так работает как надо, только на большой таблице долго, индекс как > раз по этим полям: > > select * from Table where > ((LastName = @LastName)or(@LastName is null)) and > ((FirstName = @FirstName)or(@FirstName is null)) and > ((MiddleName = @MiddleName)or(@MiddleName is null)) Так как раз НЕ НАДО, пары (LastName = @LastName)or(@LastName is null) как раз тебе " оптимизируемость " запросов и испортят. > Запрос на одну только фамилию не нулевую даёт такую статистику IO: > scan count 1, logical reads: (regular=576821 apf=323 total=577144), > physical reads: (regular=0 apf=0 total=0), apf IOs used=0 Тут индекс не берётся. > Прямой запрос на фамилию соответственно: > scan count 1, logical reads: (regular=80 apf=0 total=80), physical > reads: (regular=5 apf=0 total=5), apf IOs used=0 а тут берётся. Posted via ActualForum NNTP Server 1.4 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2009, 17:33 |
|
||
|
Поиск не по NULL
|
|||
|---|---|---|---|
|
#18+
golsa пишет: > select * from Table where > LastName = ISNULL(@LastName ,LastName) > and FirstName= ISNULL(@FirstName,FirstName) > and MiddleName= ISNULL(@MiddleName,MiddleName) Это -- сразу же убить производительность. Posted via ActualForum NNTP Server 1.4 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2009, 17:34 |
|
||
|
|

start [/forum/topic.php?fid=55&msg=36174836&tid=2010920]: |
0ms |
get settings: |
10ms |
get forum list: |
14ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
159ms |
get topic data: |
11ms |
get forum data: |
3ms |
get page messages: |
52ms |
get tp. blocked users: |
1ms |
| others: | 17ms |
| total: | 275ms |

| 0 / 0 |

Извините, этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
... ля, ля, ля ...