Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 2007.04.15;
Скачать: [xml.tar.bz2];

Вниз

сортировка в SQL по нескольким параметрам, поможите   Найти похожие ветки 

 
Шмфтнср   (2007-01-26 08:05) [0]

вопрос в следующем, время поджимает а я чет ни как не могу воткнуться в тему, с скл совсем не долго, много чего еще читать но поможите. Базюлька на msSQL server 2000
Есть две таблицы: скажем авто и клиенты, делается запрос:
dmData.qKontrakt.SQL.Text := "select * from auto, klient where auto.urn = klient.urn order by model"
все пучком, все просто. Дальше в комбо боксе отображено несколько моделей и один итем "все..." с одним тоже все ок, пишем:
procedure TfrmForm.cbModelChange(Sender: TObject);
begin

   dmData.qKontrakt.Active:=false;
   dmData.qKontrakt.SQL.Clear;

   if cbModel.Text = "Âñå..." then
     dmData.qKontrakt.SQL.Text := "select * from auto, klient where auto.urn = klient.urn order by model"
     else
       begin
         dmData.qKontrakt.SQL.Text := "select * from auto, klient where auto.urn = klient.urn AND auto.model = :ModelChoice order by model";
         dmData.qKontrakt.Parameters.ParamByName("ModelChoice").Value:= cbModel.Text;
       end;

   dmData.qKontrakt.Open;
end;

А ввот дальше хз как сделать, у меня таких комбиков 4, и по всем надо отследить параметр запроса, все ниче если есть сразу параметры выборки тоисть в 1-м к примеру ваз во втором 2110 и т.д, но как поставить чтобы допустим выбрал марку машины - он отсортирова, далее код модели он оставил выбранную марку и в них отсортировал код модели, далее цвет и  опять же из уже выбранных.
Помогите конкретным примером плиз или киньте ссылкой если гдето подобный пример обсуждался. Повторяюсь спрашиваю только из-за нехватки времени.


 
Sergey13 ©   (2007-01-26 08:21) [1]

where
    ((pole1=:param1 and :flag1=1) or :flag1=0)
and  ((pole2=:param2 and :flag2=1) or :flag2=0)
and ....


Идея понятна? С некоторыми компонентами допустимо иметь только 1 парараметр, т.е. всместо проверки парного параметра можно проверить сам параметр на нул.


 
Шмфтнср   (2007-01-26 09:02) [2]

идея понятна, сейчас покапаю


 
Шмфтнср   (2007-01-26 09:38) [3]

Чет не выходит каменный цветок, знаний не хватает, если есть возможность покажите на выше приведённом примере или поподробнее опишите.


 
Sergey13 ©   (2007-01-26 09:42) [4]

> [3] Шмфтнср   (26.01.07 09:38)

Как конкретно и что не выходит то?


 
Sergey13 ©   (2007-01-26 09:44) [5]

Кстати слово "сортировка" в твоем вопросе вроде как совсем ни при чем.


 
Шмфтнср   (2007-01-26 10:06) [6]

ну сортировка это абстрактно, конечно запросы... Вот смотри,  у меня идёт проверка непосредственно на значение итема, ты предлагаешь на нулевое значение, так? а сам запрос то как построить, так чтобы прдыдущие выборки оставались и менялись в зависимости от выбора других значений 1-го из 4-х комбиков. Извиняюсь если тупой вопрос, просто уже зациклился видимо.... Как говорится к черту зюйт вест пальцем покажи :)


 
Sergey13 ©   (2007-01-26 10:21) [7]

> [2] Шмфтнср   (26.01.07 09:02)
> идея понятна
Судя по

> [6] Шмфтнср   (26.01.07 10:06)

не очень.

Суть проста на каждое условие (твои комбобоксы) формируется условие в секции where, но таким образом, что это условие можно "заглушить". Т.е. например при :flag1=0 (в моем примере из [1]) условие pole1=:param1 просто не сработает. Остается проанализировать условия (комбобоксы) и правильно присвоить параметры. Причем не переписывая текста запроса (он получится универсальным).


 
Шмфтнср   (2007-01-26 10:52) [8]

большое спасибо, все заработало


 
SergeD   (2007-01-26 11:03) [9]


> where
>     ((pole1=:param1 and :flag1=1) or :flag1=0)
> and  ((pole2=:param2 and :flag2=1) or :flag2=0)
> and ....
>
> Идея понятна? С некоторыми компонентами допустимо иметь
> только 1 парараметр, т.е. всместо проверки парного параметра
> можно проверить сам параметр на нул.

Надо толкьо учитывать, что при использовании операции OR отключаются индексы. Если база небольшая, то это неважно, но при большом объеме данных может сильно замедлить работу


 
Шмфтнср   (2007-01-26 11:07) [10]

сейчас главное что завелось, более оптимальные решения я и сам нарою, подниму литературку. Просто время поджало.

Еще раз спасибо


 
Шмфтнср   (2007-01-26 11:08) [11]

Или есть сразу оптимальное решение чтобы не переделывать? :)) буду очень признателен


 
SergeD   (2007-01-26 11:16) [12]

Ну я обычно в событии BeforeOpen таблицы пишу обработчик:

 str:= GetFilterStr;
 Plategi.SQLs.SelectSQL.Strings[35]:= str;

где GetFilterStr написанная мной процедура, в которой считывааются все параметры из панели и формируется строка WHERE.
Ну а дальше я просто обращаюсь к свойству таблицы SQL и в нужную строку прописываю полученные результат

Как образец могу привести свой код GetFilterStr:

function TForm1.GetFilterStr: string;

 function UnMask(Txt: string): string;
 begin
   Result := Q_DelChar(Txt, ".");
   Result := Q_DelChar(Result, " ");
 end;

begin
 Result := "";
 if nom_pp.Text <> "" then
   begin
     Result := Result + " and NUM_PP = " + QuotedStr(trim(nom_pp.Text));
   end;
 if s_date.Text <> "" then
   begin
     Result := Result + " and TIME_PAY >= " + QuotedStr(s_date.Text);
   end;
 if po_date.Text <> "" then
   begin
     Result := Result + " and TIME_PAY <= " + QuotedStr(po_date.Text);
   end;
 if (SUM_PP.Text <> "") and (SUM_PP.Text <> "0") then
   begin
     Result := Result + " and SUM_PP = " + PoinToZpt(SUM_PP.Text);
   end;
 if EdNum.Text <> "" then result:= result + " and UPPER(ED_PACKET) = "+QuotedStr(AnsiUpperCase(EdNum.Text));
 if TypeDoc.Text <> "&#194;&#241;&#229;" then begin
     if TypeDoc.Text = "&#196;&#238;&#234;&#243;&#236;&#229;&#237;&#242;&#251; &#211;&#212;&#221;&#193;&#209;" then result:= result +" and TYPE_ED = 0";
     if TypeDoc.Text = "&#196;&#238;&#234;&#243;&#236;&#229;&#237;&#242;&#251; &#211;&#212;&#202;" then result:= result +" and TYPE_ED = 1";
 end;
 if rs.Text <> "" then begin
    if TipRs.Text = "&#209;&#247;&#229;&#242; &#239;&#238;&#235;&#243;&#247;&#224;&#242;&#229;&#235;&#255;" then  Result := Result + " and rs_rcp in ("+rs.Text+")"
                                      else  Result := Result + " and rs_pay in ("+rs.Text+")";
                  end;


 
Шмфтнср   (2007-01-26 11:24) [13]

хм, тоже вариант, ща буду пробовать. У меня изначально то и была идея именно считывания переменных, составления полного запроса а потом его подстановка в обработку. Ток не мог собразить... хех плохо быть бесталковому :) Спасибо


 
Sergey13 ©   (2007-01-26 11:52) [14]

> [9] SergeD   (26.01.07 11:03)
> Надо толкьо учитывать, что при использовании операции OR отключаются индексы.
Может быть. Я не знаток МССкуля.

> [12] SergeD   (26.01.07 11:16)
При таком подходе легко нарваться на другие неприятности, типа несоответствия типов. Кроме того динамический СКЛ, он и есть динамический.

Вобщем пробовать надо.


 
Шмфтнср   (2007-01-26 12:39) [15]

Может не сильно естетично но  реализовал так:
 if cbModel.Text = "&#194;&#241;&#229;..." then ModelChoice := "" else ModelChoice := " AND auto.model = " + """" + cbModel.Text + """";

 if cbKodModel.Text = "&#194;&#241;&#229;..." then KodModel := "" else KodModel :=" AND auto.kod_model = " + """" + cbKodModel.Text + """";

 if cbSFX.Text = "&#194;&#241;&#229;..." then SFXChoice := "" else SFXChoice := " AND auto.sfx = " + """" + cbSFX.Text + """";

 if cbColor.Text = "&#194;&#241;&#229;..." then ColorChoice := "" else ColorChoice := " AND auto.model = " + """" + cbColor.Text + """";

 SQLChoice := "select * from auto, klient where auto.urn = klient.urn" + ModelChoice + KodModel + SFXChoice + ColorChoice + " order by model";


 
SergeD   (2007-01-26 12:58) [16]

"""" + cbColor.Text + """" можно заменить на QuotedStr(cbColor.Text)
ИМХО, так лучше воспринимается, да и правильнее оно.


 
Шмфтнср   (2007-01-26 13:04) [17]

о! верно, сенкс


 
Desdechado ©   (2007-01-26 13:26) [18]

> """" + cbColor.Text + """" можно заменить на QuotedStr(cbColor.Text)
> ИМХО, так лучше воспринимается, да и правильнее оно.
Правильнее использовать параметры. А определять, нужно ли присваивать им значение (фактически: определять, есть ли такое условие), можно через FindParam.

> Надо толкьо учитывать, что при использовании операции OR отключаются индексы.
Что-то сильно сомнительно. Откуда такая инфа?


 
sniknik ©   (2007-01-26 14:32) [19]

>> Надо толкьо учитывать, что при использовании операции OR отключаются индексы.
> Может быть. Я не знаток МССкуля.
вряд ли. скорее если и у него был эффект отключения индекса то от другого, а приписал or, план/конкретно запрос надо смотреть.

часто пользуюсь таким примерно
DECLARE @@Field INT
SET @@Field=:Field

SELECT * FROM Table
WHERE Field=@@Field OR @@Field IS Null

or есть, индексы не страдают (план показывает индексный поиск, прям специально проверил, заинтересовало. а то и не задумывался об этом).


 
SergeD   (2007-01-26 15:35) [20]


> > Надо толкьо учитывать, что при использовании операции
> OR отключаются индексы.
> Что-то сильно сомнительно. Откуда такая инфа?

По личному опыту. Очень резко возрастало время выполнения запроса при сипользовании этого оператора. Когда перестраивал запрос так, чтобы обойтись без него, время выполнения уменьшалось на порядок (при выборке нескольких тысяч записей). Plain показал, что при OR индексы не работают.


 
Sergey13 ©   (2007-01-26 15:43) [21]

> [20] SergeD   (26.01.07 15:35)

Ну-у-у. Я думал (хоть и сомневался) это так "задумано" и прописано в доках. А в запросе написать можно что угодно, хоть с OR хоть без него, так что производительность будет в разы отличаться.

Есть например разница и от OR не зависит

select * from table where id=1 or id=2
или
select * from table where id=1 or id in (select....)


 
SergeD   (2007-01-26 15:47) [22]

Поправка. Сейчас вот дошло. При использовании оператора OR индекс отключается в том случае, если хоть по одному полю в этом операторе не построен индекс. Если индекс построе по всем полям внутри него, то, конечно, индексы работают.


 
Desdechado ©   (2007-01-26 15:50) [23]

> время выполнения уменьшалось на порядок
А план запроса "с" и "без" поглядеть не досуг?

PS систему раком можно поставить почти любым запросом, главное - знать, как поставить этот запрос


 
SergeD   (2007-01-26 15:55) [24]


> А план запроса "с" и "без" поглядеть не досуг?

А я, по вашему, на оснвоании чего сделал вывод, что индексы отключаются?

А вообще см. мой пост выше. Я пояснил при каких условиях они не работают. И использование индексированных полей вместе с не инедксированными в запросе с оператором OR сильно замедляет его выполнение


 
Sergey13 ©   (2007-01-26 15:57) [25]

> [22] SergeD   (26.01.07 15:47)
> Поправка. Сейчас вот дошло. При использовании оператора
> OR индекс отключается в том случае, если хоть по одному
> полю в этом операторе не построен индекс. Если индекс построе
> по всем полям внутри него, то, конечно, индексы работают.

Я не утверждаю, но подозреваю, что важен так же порядок полей в условии и в индексе. А так же если в индексе есть поля стоящие в условии первыми, то индекс может быть задействован.
Но точный ответ на вопрос об использовании индекса дает безусловно только план.


 
b z   (2007-01-26 15:58) [26]


> DECLARE @@Field INT
> SET @@Field=:Field
>
> SELECT * FROM Table
> WHERE Field=@@Field OR @@Field IS Null

Тут, плохо то, что если вместо "Field=@@Field" будет большой подзапрос, то это не очень. Т.к. при OR всегда проверяются оба выражения (если не прав - поправте, тестировали вроде так и есть).
Иногда можно проскочить через case when примерно так:
where 1 = case when @
is null then 1 else (крутой запрос который должен вернуть 1 в случае совпадения) end.
Можно еще coalesce применить.

Недостаток подходов в том что в клиентском запросе не пройдет (или не всегда).
Поэтому, при использовании таких серверов, как в [0] все-таки надо писать сохраненные процедуры, и не думать о том как много в них строчек. Они на то и есть. :)  ИМХО


 
evvcom ©   (2007-01-26 16:54) [27]

> [26] b z   (26.01.07 15:58)
> если вместо "Field=@@Field" будет большой подзапрос

Какой подзапрос? Ты вопрос читал?

> [25] Sergey13 ©   (26.01.07 15:57)
> но подозреваю, что важен так же порядок полей в условии
> и в индексе

В индексе, думаю, да важен, а в запросе вряд ли. Запрос все равно оптимизатор по-своему поймет и что надо куда надо переставит. Хотя я тоже не знаток MSSQL. Сужу по ораклу.



Страницы: 1 вся ветка

Форум: "Базы";
Текущий архив: 2007.04.15;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.53 MB
Время: 0.06 c
2-1174547169
sergeyst
2007-03-22 10:06
2007.04.15
Нужно ли осовбождать память?


11-1156073941
case
2006-08-20 15:39
2007.04.15
Укажите ошибку (почему прга не реагирует на мессаги) .


2-1174887016
IgorMish
2007-03-26 09:30
2007.04.15
CheckBox в DBGrid


3-1169624170
truegosha
2007-01-24 10:36
2007.04.15
ADO и транзакции


2-1174658224
Гость_
2007-03-23 16:57
2007.04.15
Не могу выбрать из DBLookUpComboBox





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский