Lotsia PLM: Форум по семейству систем PLM/PDM/TDM/ERP/Workflow

Для специалистов по внедрению систем, профессиональных администраторов и пользователей.
Текущее время: 17 июл 2018, 07:08

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 8 ] 
Автор Сообщение
 Заголовок сообщения: Собственный поиск объектов (LSQuery)
СообщениеДобавлено: 02 сен 2009, 15:39 
Не в сети
Активный участник
Аватара пользователя

Зарегистрирован: 15 июл 2004, 15:12
Сообщения: 420
Откуда: Подольск
Благодарил (а): 8 раз.
Поблагодарили: 2 раз.
В этой теме предлагаю обмениваться своими достижениями и соображениями в части организации поиска объектов при помощи объекта LSQuery.

Для Sybase SQL Anywhere 10 есть(была) проблема с производительностью стандартного поиска объектов по нескольким атрибутам. Если же между атрибутами есть OR, проблема производительности должна быть актуальна для всех СУБД.
Благодаря приведенному ниже варианту, время поиска удалось существенно снизить, в ряде случаев, более чем на порядок.
Удалось избежать пагубного влияния OR между атрибутами на производительность поиска.
"NOT IN" вместо "<>" также способствует росту производительности.

Начнем со скрипта.
Код:
Option Explicit
Sub Search()
  dim SearchDS,Cond,i,iOpen,iClose,attr_cnt,lAttribID
  dim iLO,cLO,rValue
  if LSQuery.IsCustomSet("LsObjByAttrib") then
    set SearchDS=LSQuery.CustomParam("LsObjByAttrib")
    if SearchDS.Count>1 then
      attr_cnt=0
      iLO=0
      iOpen=0
      For i=1 To SearchDS.Count
        Set Cond=SearchDS.Item(i)
        if Cond.lType="A" then attr_cnt=attr_cnt+1
        if attr_cnt=0 then
          iLO=i
          iOpen=iOpen+Cond.bOpen-Cond.bClose
        end if
      Next
      if attr_cnt>1 and iLO>0 and iOpen=0 then
        For i=1 to ILO
          set Cond=SearchDS.Item(i)
          rValue=PrepareStrValue(Cond.rValue)
          if (Cond.Oper="like" or Cond.Oper="not like") and right(rValue,1)<>"%" then rValue=rValue+"%"
          Select Case Cond.lValue
            Case "D"             
              Select Case Cond.Oper
                Case "exists"
                  cLO=cLO+String(Cond.bOpen,"(")+_
                    "lsdbo.object_reference_view.description > '' "+_
                    +String(Cond.bClose,")")
                Case "not exists"
                  cLO=cLO+String(Cond.bOpen,"(")+_
                    "lsdbo.object_reference_view.description = '' "+_
                    +String(Cond.bClose,")")
                Case Else
                  cLO=cLO+String(Cond.bOpen,"(")+_
                    "lsdbo.object_reference_view.description "+Cond.Oper+" '"+_
                    rValue+"' "+String(Cond.bClose,")")
              End Select
            Case "T"
              Select Case Cond.Oper
                Case "exists"
                  cLO=cLO+String(Cond.bOpen,"(")+_
                    "lsdbo.object_type_view.description > '' "+_
                    +String(Cond.bClose,")")
                Case "not exists"
                  cLO=cLO+String(Cond.bOpen,"(")+_
                    "lsdbo.object_type_view.description = '' "+_
                    +String(Cond.bClose,")")
                Case Else
                  cLO=cLO+String(Cond.bOpen,"(")+_
                    "lsdbo.object_type_view.description "+Cond.Oper+" '"+_
                    rValue+"' "+String(Cond.bClose,")")
              End Select
            Case "M"
              Select Case Cond.Oper
                Case "exists"
                  cLO=cLO+String(Cond.bOpen,"(")+_
                    "lsdbo.object_type_view.mnemo > '' "+_
                    +String(Cond.bClose,")")
                Case "not exists"
                  cLO=cLO+String(Cond.bOpen,"(")+_
                    "lsdbo.object_type_view.mnemo = '' "+_
                    +String(Cond.bClose,")")
                Case Else
                  cLO=cLO+String(Cond.bOpen,"(")+_
                    "lsdbo.object_type_view.mnemo "+Cond.Oper+" '"+_
                    rValue+"' "+String(Cond.bClose,")")
              End Select
            Case "C"
              Select Case Cond.Oper
                Case "exists"
                  cLO=cLO+String(Cond.bOpen,"(")+_
                    "lsdbo.object_type_view.object_type > '' "+_
                    +String(Cond.bClose,")")
                Case "not exists"
                  cLO=cLO+String(Cond.bOpen,"(")+_
                    "lsdbo.object_type_view.object_type = '' "+_
                    +String(Cond.bClose,")")
                Case Else
                  cLO=cLO+String(Cond.bOpen,"(")+_
                    "lsdbo.object_type_view.object_type "+Cond.Oper+" '"+_
                    rValue+"' "+String(Cond.bClose,")")
              End Select           
          End Select
          cLO=cLO+" "+Cond.Logic+" "
        Next
      else
        iLO=0
      end if
      iLO=iLO+1
      if attr_cnt>1 then
        LSTransaction.Execute("DELETE FROM lsdbo.aln_misc_LSQueryCond")
        For i=iLO To SearchDS.Count
          Set Cond=SearchDS.Item(i)
          if i=iLO then iOpen=1 else iOpen=0
          if i=SearchDS.Count then iClose=1 else iClose=0
          if IsEmpty(Cond.lAttribID) then lAttribID=0 else lAttribID=Cond.lAttribID
          LSTransaction.Execute(_
            "INSERT INTO lsdbo.aln_misc_LSQueryCond(sNum,bOpen,lType,lValue,lAttribID,Oper,rValue,bClose,Logic,DataType)"+_
            " VALUES("+CStr(i*1000)+","+CStr(Cond.bOpen+iOpen)+",'"+Cond.lType+"','"+Cond.lValue+"',"+_
            CStr(lAttribID)+",'"+Cond.Oper+"','"+PrepareStrValue(Cond.rValue)+"',"+_
            CStr(Cond.bClose+iClose)+",'"+Cond.Logic+"','"+Chr(Cond.DataType)+"')")
        Next
        call LSQuery.CustomWhere("LsObjByAttrib",_
          cLO+"lsdbo.object_reference_view.id in(SELECT id FROM lsdbo.aln_misc_LSQuery())")
      end if
    end if
  end if
End Sub
Function PrepareStrValue(str_val)
  str_val=replace(str_val,"'","''")
  str_val=replace(str_val,vbnewline,"\x0D\x0A")
  PrepareStrValue=str_val
End Function

Условия поиска сохраняются в таблице
Код:
CREATE GLOBAL TEMPORARY TABLE "LSDBO"."aln_misc_LSQueryCond" (
    "sNum"                           integer NOT NULL
   ,"bOpen"                          integer NULL
   ,"lType"                          char(1) NULL
   ,"lValue"                         char(1) NULL
   ,"lAttribID"                      numeric(18,0) NULL
   ,"Oper"                           varchar(20) NULL
   ,"rValue"                         varchar(255) NULL
   ,"bClose"                         integer NULL
   ,"Logic"                          varchar(20) NULL
   ,"DataType"                       char(1) NULL
   ,PRIMARY KEY ("sNum")
) NOT TRANSACTIONAL

Далее текст поисковых процедур на WatcomSQL:
№1
Код:
ALTER PROCEDURE "LSDBO"."aln_misc_LSQuery"()
RESULT(id numeric(18))
BEGIN
   declare local temporary table #res(
      sNum integer,
      id numeric(18),
   )not transactional;
   declare @sNum1 integer;
   declare @sNum2 integer;
   declare @SNum_res integer;
   declare @lType1 char(1);
   declare @lType2 char(1);
   declare @Logic varchar(20);
   declare @Logic_res varchar(20);
   declare @bOpen_res integer;
   declare @bClose_res integer;
   declare @lAttribID1 numeric(18);
   declare @lAttribID2 numeric(18);
   declare @lValue1 char(1);
   declare @lValue2 char(1);
   declare @rValue1 varchar(255);
   declare @rValue2 varchar(255);
   declare @Oper1 varchar(20);
   declare @Oper2 varchar(20);
   declare @DataType1 char(1);
   declare @DataType2 char(1);

   create index aln_misc_LSQuery_1_ndx on #res(sNum);

   //Убираем избыточные скобки
   update lsdbo.aln_misc_LSQueryCond set
      bOpen=bOpen-(if bOpen<bClose then bOpen else bClose endif),
      bClose=bClose-(if bOpen<bClose then bOpen else bClose endif)
      where bOpen>0 and bClose>0;
   while exists(select sNum from lsdbo.aln_misc_LSQueryCond where bClose>0)loop
      //Определяем номера условий/множеств
      select min(sNum) into @sNum2 from lsdbo.aln_misc_LSQueryCond where bClose>0;
      select max(sNum) into @sNum1 from lsdbo.aln_misc_LSQueryCond where sNum<@sNum2;      
      set @sNum_res=@sNum1-1;
      select first bOpen,lType,lValue,lAttribID,Oper,rValue,Logic,DataType
         into @bOpen_res,@lType1,@lValue1,@lAttribID1,@Oper1,@rValue1,@Logic,@DataType1
         from lsdbo.aln_misc_LSQueryCond where sNum=@sNum1;
      select first bClose,lType,lValue,lAttribID,Oper,rValue,Logic,DataType
         into @bClose_res,@lType2,@lValue2,@lAttribID2,@Oper2,@rValue2,@Logic_res,@DataType2
         from lsdbo.aln_misc_LSQueryCond where sNum=@sNum2;
      //Обрабатываем связку @cur_sNum и @prev_sNum
      case @Logic
         when 'and' then
            insert into #res(sNum,id)
              select @sNum_res,dt1.id from
               (select id from aln_misc_LSQuerySingleSet(@lType1,@lValue1,
                  @lAttribID1,@Oper1,@rValue1,@DataType1)) as dt1(id)
               join
               (select id from aln_misc_LSQuerySingleSet(@lType2,@lValue2,
                  @lAttribID2,@Oper2,@rValue2,@DataType2)) as dt2(id)
               on dt1.id=dt2.id;
         when 'or' then
            insert into #res(sNum,id)
               select @sNum_res,id from aln_misc_LSQuerySingleSet(@lType1,@lValue1,
                  @lAttribID1,@Oper1,@rValue1,@DataType1)
               union all
               select @sNum_res,id from aln_misc_LSQuerySingleSet(@lType2,@lValue2,
                  @lAttribID2,@Oper2,@rValue2,@DataType2);
         when 'and not' then
            insert into #res(sNum,id)
               select @sNum_res,dt1.id from
               (select id from aln_misc_LSQuerySingleSet(@lType1,@lValue1,
                  @lAttribID1,@Oper1,@rValue1,@DataType1)) as dt1(id)
               left outer join
               (select id from aln_misc_LSQuerySingleSet(@lType2,@lValue2,
                  @lAttribID2,@Oper2,@rValue2,@DataType2)) as dt2(id)
               on dt1.id=dt2.id
               where dt2.id is null;
         when 'or not' then
            insert into #res(sNum,id)
               select @sNum_res,id from aln_misc_LSQuerySingleSet(@lType1,@lValue1,
                  @lAttribID1,@Oper1,@rValue1,@DataType1)
               union all
               select @sNum_res,id from object_reference
                  where id not in(select id from aln_misc_LSQuerySingleSet(@lType2,@lValue2,@lAttribID2,@Oper2,@rValue2,@DataType2));
      end case;
      //Заменяем обработанные условия/множества полученным результаттом
      insert into lsdbo.aln_misc_LSQueryCond(sNum,lType,lAttribID,bOpen,bClose,Logic)
         values(@sNum_res,'_',@sNum_res,@bOpen_res,@bClose_res,@Logic_res);
      delete from lsdbo.aln_misc_LSQueryCond where sNum in(@sNum1,@sNum2);
      //Убираем избыточные скобки
      update lsdbo.aln_misc_LSQueryCond set
         bOpen=bOpen-(if bOpen<bClose then bOpen else bClose endif),
         bClose=bClose-(if bOpen<bClose then bOpen else bClose endif)
         where bOpen>0 and bClose>0;
   end loop;
   select id from #res where sNum=@sNum_res;
END

№2
Код:
ALTER PROCEDURE "LSDBO"."aln_misc_LSQuerySingleSet"(in @lType char(1),in @lValue char(1),in @lAttribID numeric(18),
   in @Oper varchar(20),in @rValue varchar(255),in @DataType char(1))
RESULT (id numeric(18))
BEGIN
case @lType   
   When'A' then
      case @Oper
         when 'exists' then
            SELECT object_id as id FROM lsdbo.attrib_value force index(attrib_key1) WHERE attrib_id=@lAttribID;
         when 'not exists' then
            SELECT id FROM lsdbo.object_reference
               WHERE id NOT IN(SELECT object_id FROM lsdbo.attrib_value force index(attrib_key1) WHERE attrib_id=@lAttribID);
         when 'like'   Then      
            case @DataType
               when 'S' Then
                  set @rValue=(if coalesce(right(@rValue,1),'')<>'%' then @rValue+'%' else @rValue endif);
                  SELECT av.object_id as id
                     FROM lsdbo.value_string as vt force index(attrib_ndx3) JOIN lsdbo.attrib_value as av force index(attrib_value_av_ndx)
                        on vt.attrib_id=av.attrib_id and vt.id=av.value_id
                     WHERE vt.attrib_id=@lAttribID and vt.value like @rValue;
               when 'N' Then
                  SELECT av.object_id as id
                     FROM lsdbo.value_numeric as vt force index(attrib_ndx7) JOIN lsdbo.attrib_value as av force index(attrib_value_av_ndx)
                        on vt.attrib_id=av.attrib_id and vt.id=av.value_id
                     WHERE vt.attrib_id=@lAttribID and vt.value like cast(@rValue as double);
               when 'T' Then
                  SELECT av.object_id as id
                     FROM lsdbo.value_datetime as vt force index(attrib_ndx4) JOIN lsdbo.attrib_value as av force index(attrib_value_av_ndx)
                        on vt.attrib_id=av.attrib_id and vt.id=av.value_id
                     WHERE vt.attrib_id=@lAttribID and vt.value like convert(datetime,@rValue,104);
            end case;
         when 'not like'   Then      
            case @DataType
               when 'S' Then
                  set @rValue=(if coalesce(right(@rValue,1),'')<>'%' then @rValue+'%' else @rValue endif);
                  SELECT av.object_id as id
                     FROM lsdbo.value_string as vt force index(attrib_ndx3) JOIN lsdbo.attrib_value as av force index(attrib_value_av_ndx)
                        on vt.attrib_id=av.attrib_id and vt.id=av.value_id
                     WHERE vt.attrib_id=@lAttribID and vt.value not like @rValue;
               when 'N' Then
                  SELECT av.object_id as id
                     FROM lsdbo.value_numeric as vt force index(attrib_ndx7) JOIN lsdbo.attrib_value as av force index(attrib_value_av_ndx)
                        on vt.attrib_id=av.attrib_id and vt.id=av.value_id
                     WHERE vt.attrib_id=@lAttribID and vt.value not like cast(@rValue as double);
               when 'T' Then
                  SELECT av.object_id as id
                     FROM lsdbo.value_datetime as vt force index(attrib_ndx4) JOIN lsdbo.attrib_value as av force index(attrib_value_av_ndx)
                        on vt.attrib_id=av.attrib_id and vt.id=av.value_id
                     WHERE vt.attrib_id=@lAttribID and vt.value not like convert(datetime,@rValue,104);
            end case;
         when '=' Then
            case @DataType
               when 'S' Then
                  SELECT av.object_id as id
                     FROM lsdbo.value_string as vt force index(attrib_ndx3) JOIN lsdbo.attrib_value as av force index(attrib_value_av_ndx)
                        on vt.attrib_id=av.attrib_id and vt.id=av.value_id
                     WHERE vt.attrib_id=@lAttribID and vt.value = @rValue;
               when 'N' Then
                  SELECT av.object_id as id
                     FROM lsdbo.value_numeric as vt force index(attrib_ndx7) JOIN lsdbo.attrib_value as av force index(attrib_value_av_ndx)
                        on vt.attrib_id=av.attrib_id and vt.id=av.value_id
                     WHERE vt.attrib_id=@lAttribID and vt.value = cast(@rValue as double);
               when 'T' Then
                  SELECT av.object_id as id
                     FROM lsdbo.value_datetime as vt force index(attrib_ndx4) JOIN lsdbo.attrib_value as av force index(attrib_value_av_ndx)
                        on vt.attrib_id=av.attrib_id and vt.id=av.value_id
                     WHERE vt.attrib_id=@lAttribID and vt.value = convert(datetime,@rValue,104);
            end case;
         when '>' Then
            case @DataType
               when 'S' Then
                  SELECT av.object_id as id
                     FROM lsdbo.value_string as vt force index(attrib_ndx3) JOIN lsdbo.attrib_value as av force index(attrib_value_av_ndx)
                        on vt.attrib_id=av.attrib_id and vt.id=av.value_id
                     WHERE vt.attrib_id=@lAttribID and vt.value > @rValue;
               when 'N' Then
                  SELECT av.object_id as id
                     FROM lsdbo.value_numeric as vt force index(attrib_ndx7) JOIN lsdbo.attrib_value as av force index(attrib_value_av_ndx)
                        on vt.attrib_id=av.attrib_id and vt.id=av.value_id
                     WHERE vt.attrib_id=@lAttribID and vt.value > cast(@rValue as double);
               when 'T' Then
                  SELECT av.object_id as id
                     FROM lsdbo.value_datetime as vt force index(attrib_ndx4) JOIN lsdbo.attrib_value as av force index(attrib_value_av_ndx)
                        on vt.attrib_id=av.attrib_id and vt.id=av.value_id
                     WHERE vt.attrib_id=@lAttribID and vt.value > convert(datetime,@rValue,104);
            end case;
         when '>=' Then
            case @DataType
               when 'S' Then
                  SELECT av.object_id as id
                     FROM lsdbo.value_string as vt force index(attrib_ndx3) JOIN lsdbo.attrib_value as av force index(attrib_value_av_ndx)
                        on vt.attrib_id=av.attrib_id and vt.id=av.value_id
                     WHERE vt.attrib_id=@lAttribID and vt.value >= @rValue;
               when 'N' Then
                  SELECT av.object_id as id
                     FROM lsdbo.value_numeric as vt force index(attrib_ndx7) JOIN lsdbo.attrib_value as av force index(attrib_value_av_ndx)
                        on vt.attrib_id=av.attrib_id and vt.id=av.value_id
                     WHERE vt.attrib_id=@lAttribID and vt.value >= cast(@rValue as double);
               when 'T' Then
                  SELECT av.object_id as id
                     FROM lsdbo.value_datetime as vt force index(attrib_ndx4) JOIN lsdbo.attrib_value as av force index(attrib_value_av_ndx)
                        on vt.attrib_id=av.attrib_id and vt.id=av.value_id
                     WHERE vt.attrib_id=@lAttribID and vt.value >= convert(datetime,@rValue,104);
            end case;
         when '<' Then
            case @DataType
               when 'S' Then
                  SELECT av.object_id as id
                     FROM lsdbo.value_string as vt force index(attrib_ndx3) JOIN lsdbo.attrib_value as av force index(attrib_value_av_ndx)
                        on vt.attrib_id=av.attrib_id and vt.id=av.value_id
                     WHERE vt.attrib_id=@lAttribID and vt.value < @rValue;
               when 'N' Then
                  SELECT av.object_id as id
                     FROM lsdbo.value_numeric as vt force index(attrib_ndx7) JOIN lsdbo.attrib_value as av force index(attrib_value_av_ndx)
                        on vt.attrib_id=av.attrib_id and vt.id=av.value_id
                     WHERE vt.attrib_id=@lAttribID and vt.value < cast(@rValue as double);
               when 'T' Then
                  SELECT av.object_id as id
                     FROM lsdbo.value_datetime as vt force index(attrib_ndx4) JOIN lsdbo.attrib_value as av force index(attrib_value_av_ndx)
                        on vt.attrib_id=av.attrib_id and vt.id=av.value_id
                     WHERE vt.attrib_id=@lAttribID and vt.value < convert(datetime,@rValue,104);
            end case;
         when '<=' Then
            case @DataType
               when 'S' Then
                  SELECT av.object_id as id
                     FROM lsdbo.value_string as vt force index(attrib_ndx3) JOIN lsdbo.attrib_value as av force index(attrib_value_av_ndx)
                        on vt.attrib_id=av.attrib_id and vt.id=av.value_id
                     WHERE vt.attrib_id=@lAttribID and vt.value <= @rValue;
               when 'N' Then
                  SELECT av.object_id as id
                     FROM lsdbo.value_numeric as vt force index(attrib_ndx7) JOIN lsdbo.attrib_value as av force index(attrib_value_av_ndx)
                        on vt.attrib_id=av.attrib_id and vt.id=av.value_id
                     WHERE vt.attrib_id=@lAttribID and vt.value <= cast(@rValue as double);
               when 'T' Then
                  SELECT av.object_id as id
                     FROM lsdbo.value_datetime as vt force index(attrib_ndx4) JOIN lsdbo.attrib_value as av force index(attrib_value_av_ndx)
                        on vt.attrib_id=av.attrib_id and vt.id=av.value_id
                     WHERE vt.attrib_id=@lAttribID and vt.value <= convert(datetime,@rValue,104);
            end case;
         when '<>' Then
            case @DataType
               when 'S' Then
                  SELECT av.object_id as id
                     FROM lsdbo.value_string as vt force index(attrib_ndx3) JOIN lsdbo.attrib_value as av force index(attrib_value_av_ndx)
                        on vt.attrib_id=av.attrib_id and vt.id=av.value_id
                     WHERE vt.attrib_id=@lAttribID and vt.value not in(@rValue);
               when 'N' Then
                  SELECT av.object_id as id
                     FROM lsdbo.value_numeric as vt force index(attrib_ndx7) JOIN lsdbo.attrib_value as av force index(attrib_value_av_ndx)
                        on vt.attrib_id=av.attrib_id and vt.id=av.value_id
                     WHERE vt.attrib_id=@lAttribID and vt.value not in(cast(@rValue as double));
               when 'T' Then
                  SELECT av.object_id as id
                     FROM lsdbo.value_datetime as vt force index(attrib_ndx4) JOIN lsdbo.attrib_value as av force index(attrib_value_av_ndx)
                        on vt.attrib_id=av.attrib_id and vt.id=av.value_id
                     WHERE vt.attrib_id=@lAttribID and vt.value not in(convert(datetime,@rValue,104));
            end case;
      end case;
   when 'O' then
      case @lValue
         when 'D' then
            case @Oper
               when 'exists' then
                  SELECT id FROM lsdbo.object_reference force index(object_reference_desc_ndx) where description>'';
               when 'not exists' then
                  SELECT id FROM lsdbo.object_reference force index(object_reference_desc_ndx) where description='';;
               when 'like' then
                  set @rValue=(if coalesce(right(@rValue,1),'')<>'%' then @rValue+'%' else @rValue endif);
                  SELECT id FROM lsdbo.object_reference force index(object_reference_desc_ndx) where description like @rValue;
               when 'not like' then
                  set @rValue=(if coalesce(right(@rValue,1),'')<>'%' then @rValue+'%' else @rValue endif);
                  SELECT id FROM lsdbo.object_reference force index(object_reference_desc_ndx) where description not like @rValue;
               when '=' then
                  SELECT id FROM lsdbo.object_reference force index(object_reference_desc_ndx) where description = @rValue;
               when '>' then
                  SELECT id FROM lsdbo.object_reference force index(object_reference_desc_ndx) where description > @rValue;
               when '>=' then
                  SELECT id FROM lsdbo.object_reference force index(object_reference_desc_ndx) where description >= @rValue;
               when '<' then
                  SELECT id FROM lsdbo.object_reference force index(object_reference_desc_ndx) where description < @rValue;
               when '<=' then
                  SELECT id FROM lsdbo.object_reference force index(object_reference_desc_ndx) where description <= @rValue;
               when '<>' then
                  SELECT id FROM lsdbo.object_reference force index(object_reference_desc_ndx) where description not in(@rValue);
            end case;
         when 'T' then
            case @Oper
               when 'exists' then
                  SELECT o.id   FROM lsdbo.object_type as ot JOIN lsdbo.object_reference as o force index(object_reference)
                     on ot.id=o.type_id where ot.description > '';
               when 'not exists' then
                  SELECT o.id   FROM lsdbo.object_type as ot JOIN lsdbo.object_reference as o force index(object_reference)
                     on ot.id=o.type_id where ot.description='';;
               when 'like' then
                  set @rValue=(if coalesce(right(@rValue,1),'')<>'%' then @rValue+'%' else @rValue endif);
                  SELECT o.id   FROM lsdbo.object_type as ot JOIN lsdbo.object_reference as o force index(object_reference)
                     on ot.id=o.type_id where ot.description like @rValue;
               when 'not like' then
                  set @rValue=(if coalesce(right(@rValue,1),'')<>'%' then @rValue+'%' else @rValue endif);
                  SELECT o.id   FROM lsdbo.object_type as ot JOIN lsdbo.object_reference as o force index(object_reference)
                     on ot.id=o.type_id where ot.description not like @rValue;
               when '=' then
                  SELECT o.id   FROM lsdbo.object_type as ot JOIN lsdbo.object_reference as o force index(object_reference)
                     on ot.id=o.type_id where ot.description = @rValue;
               when '>' then
                  SELECT o.id   FROM lsdbo.object_type as ot JOIN lsdbo.object_reference as o force index(object_reference)
                     on ot.id=o.type_id where ot.description > @rValue;
               when '>=' then
                  SELECT o.id   FROM lsdbo.object_type as ot JOIN lsdbo.object_reference as o force index(object_reference)
                     on ot.id=o.type_id where ot.description >= @rValue;
               when '<' then
                  SELECT o.id   FROM lsdbo.object_type as ot JOIN lsdbo.object_reference as o force index(object_reference)
                     on ot.id=o.type_id where ot.description < @rValue;
               when '<=' then
                  SELECT o.id   FROM lsdbo.object_type as ot JOIN lsdbo.object_reference as o force index(object_reference)
                     on ot.id=o.type_id where ot.description <= @rValue;
               when '<>' then
                  SELECT o.id   FROM lsdbo.object_type as ot JOIN lsdbo.object_reference as o force index(object_reference)
                     on ot.id=o.type_id where ot.description not in(@rValue);
            end case;
         when 'M' then
            case @Oper
               when 'exists' then
                  SELECT o.id   FROM lsdbo.object_type as ot JOIN lsdbo.object_reference as o force index(object_reference)
                     on ot.id=o.type_id where ot.mnemo > '';
               when 'not exists' then
                  SELECT o.id   FROM lsdbo.object_type as ot JOIN lsdbo.object_reference as o force index(object_reference)
                     on ot.id=o.type_id where ot.mnemo='';;
               when 'like' then
                  set @rValue=(if coalesce(right(@rValue,1),'')<>'%' then @rValue+'%' else @rValue endif);
                  SELECT o.id   FROM lsdbo.object_type as ot JOIN lsdbo.object_reference as o force index(object_reference)
                     on ot.id=o.type_id where ot.mnemo like @rValue;
               when 'not like' then
                  set @rValue=(if coalesce(right(@rValue,1),'')<>'%' then @rValue+'%' else @rValue endif);
                  SELECT o.id   FROM lsdbo.object_type as ot JOIN lsdbo.object_reference as o force index(object_reference)
                     on ot.id=o.type_id where ot.mnemo not like @rValue;
               when '=' then
                  SELECT o.id   FROM lsdbo.object_type as ot JOIN lsdbo.object_reference as o force index(object_reference)
                     on ot.id=o.type_id where ot.mnemo = @rValue;
               when '>' then
                  SELECT o.id   FROM lsdbo.object_type as ot JOIN lsdbo.object_reference as o force index(object_reference)
                     on ot.id=o.type_id where ot.mnemo > @rValue;
               when '>=' then
                  SELECT o.id   FROM lsdbo.object_type as ot JOIN lsdbo.object_reference as o force index(object_reference)
                     on ot.id=o.type_id where ot.mnemo >= @rValue;
               when '<' then
                  SELECT o.id   FROM lsdbo.object_type as ot JOIN lsdbo.object_reference as o force index(object_reference)
                     on ot.id=o.type_id where ot.mnemo < @rValue;
               when '<=' then
                  SELECT o.id   FROM lsdbo.object_type as ot JOIN lsdbo.object_reference as o force index(object_reference)
                     on ot.id=o.type_id where ot.mnemo <= @rValue;
               when '<>' then
                  SELECT o.id   FROM lsdbo.object_type as ot JOIN lsdbo.object_reference as o force index(object_reference)
                     on ot.id=o.type_id where ot.mnemo not in(@rValue);
            end case;
         when 'C' then
            case @Oper
               when 'exists' then
                  SELECT o.id   FROM lsdbo.object_type as ot JOIN lsdbo.object_reference as o force index(object_reference)
                     on ot.id=o.type_id where ot.object_type > '';
               when 'not exists' then
                  SELECT o.id   FROM lsdbo.object_type as ot JOIN lsdbo.object_reference as o force index(object_reference)
                     on ot.id=o.type_id where ot.object_type='';;
               when 'like' then
                  set @rValue=(if coalesce(right(@rValue,1),'')<>'%' then @rValue+'%' else @rValue endif);
                  SELECT o.id   FROM lsdbo.object_type as ot JOIN lsdbo.object_reference as o force index(object_reference)
                     on ot.id=o.type_id where ot.object_type like @rValue;
               when 'not like' then
                  set @rValue=(if coalesce(right(@rValue,1),'')<>'%' then @rValue+'%' else @rValue endif);
                  SELECT o.id   FROM lsdbo.object_type as ot JOIN lsdbo.object_reference as o force index(object_reference)
                     on ot.id=o.type_id where ot.object_type not like @rValue;
               when '=' then
                  SELECT o.id   FROM lsdbo.object_type as ot JOIN lsdbo.object_reference as o force index(object_reference)
                     on ot.id=o.type_id where ot.object_type = @rValue;
               when '>' then
                  SELECT o.id   FROM lsdbo.object_type as ot JOIN lsdbo.object_reference as o force index(object_reference)
                     on ot.id=o.type_id where ot.object_type > @rValue;
               when '>=' then
                  SELECT o.id   FROM lsdbo.object_type as ot JOIN lsdbo.object_reference as o force index(object_reference)
                     on ot.id=o.type_id where ot.object_type >= @rValue;
               when '<' then
                  SELECT o.id   FROM lsdbo.object_type as ot JOIN lsdbo.object_reference as o force index(object_reference)
                     on ot.id=o.type_id where ot.object_type < @rValue;
               when '<=' then
                  SELECT o.id   FROM lsdbo.object_type as ot JOIN lsdbo.object_reference as o force index(object_reference)
                     on ot.id=o.type_id where ot.object_type <= @rValue;
               when '<>' then
                  SELECT o.id   FROM lsdbo.object_type as ot JOIN lsdbo.object_reference as o force index(object_reference)
                     on ot.id=o.type_id where ot.object_type not in(@rValue);
            end case;
      end case;
   when '_' then
      select id from #res where sNum=@lAttribID;
end case;
END

_________________
Ах и с ними невозможно
И без них никак нельзя


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 03 сен 2009, 06:45 
Не в сети
Активный участник
Аватара пользователя

Зарегистрирован: 24 авг 2006, 08:06
Сообщения: 1646
Откуда: 55.745578,37.665825
Благодарил (а): 8 раз.
Поблагодарили: 3 раз.
вопрос - а что за объект LSQuery? вообще нигде не нашел, и второе а в чем идея ускорения - в двух словах?

_________________

Софт - RicCRM<<LotsiaPDM(4.40)<<MsSQL(5/8)
Уровень администрирования - Альтернативный



Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 03 сен 2009, 10:14 
Не в сети
Активный участник
Аватара пользователя

Зарегистрирован: 15 июл 2004, 15:12
Сообщения: 420
Откуда: Подольск
Благодарил (а): 8 раз.
Поблагодарили: 2 раз.
LSQuery используется для подмены стандартного поиска Лоции собственным. Описан в руководстве "Скрипты".
Принцип стандартного поиска Лоции состоит в том, что все условия записываются в условия WHERE одного SELECTа. Т.е. используется принцип "все яйца в одну корзину", что удобно, но не всегда эффективно. Соответственно, в ряде случаев получаются такие запросы, что оптимизатор на них отрабатывает не лучшим образом. Особенно, если в условиях есть ИЛИ. Резюме: отличные результаты для большинства простых запросов и зачастую неудовлетворительная производительность поиска со сложными условиями.
Суть моего подхода: для каждой строки условия отдельно вычисляется множество удовлетворяющих ему объектов, затем множества пересекаются INNER JOIN (И) LEFT OUTER JOIN (И НЕ) или объединяются UNION (ИЛИ) (ИЛИ НЕ). Для получения каждого множества используются простые запросы, проблем с оптимизацией которых не возникает. Т.е. используется принцип "разделяй и властвуй". Резюме: удовлетворительное время поиска для запросов любой сложности при большей ресурсоемкости (относительно высокий процент утилизации процессора сервера СУБД).
Для поисковых запросов, где больше одного атрибута использую свой метод, для остальных стандартные средства поиска. Плюс, при возможности, условия по типам и описаниям объектов стараюсь выводить в условие WHERE т.к. обработка этих условий как отдельных множеств наиболее ресурсоемка.

_________________
Ах и с ними невозможно
И без них никак нельзя


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 03 сен 2009, 10:53 
Не в сети
Активный участник
Аватара пользователя

Зарегистрирован: 24 авг 2006, 08:06
Сообщения: 1646
Откуда: 55.745578,37.665825
Благодарил (а): 8 раз.
Поблагодарили: 3 раз.
Спасибо!
...в мануале и не посмотрел :wink: Знаешь - был бы отладчик нормальный - я бы лично с удовольствием посмотрел твой код (wathes) по шагам... вообще с удивлением узнал что в окне выбора объектов есть скрипты - никогда этим окном не пользуемся вообще. А идея - то что надо!
ps
а функций оказывается действительно много добавили - еще бы примеров конкретных с комментариями...
глядишь и уйдут в прошлое макросы и настанет эпоха водолея.. упс.. скриптов и vba :wink:

_________________

Софт - RicCRM<<LotsiaPDM(4.40)<<MsSQL(5/8)
Уровень администрирования - Альтернативный



Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 27 июн 2010, 17:04 
Не в сети
Активный участник
Аватара пользователя

Зарегистрирован: 24 авг 2006, 08:06
Сообщения: 1646
Откуда: 55.745578,37.665825
Благодарил (а): 8 раз.
Поблагодарили: 3 раз.
попробовал скрипт в поиске объектов - есть пара вопросов, отвлеченных...
как я понял скрипт просто расширяет секцию where... у стандартного запроса
1 можно ли в скрипте, здесь, перед началом допустим поиска организовать выбор дополнительных условий через msgbox - типа выберите то или это, или в принципе - хотите использовать скрипт или нет... - у меня на msgbox как таковой ругается - т.е. здесь интерпретатор обрезанный или... что?
в плане реализации выбора например
-дочерние объекты
-родительские объекты
-простой поиск
2 а если выбор дополнительных условий нельзя организовать в виде диалога, только через сохранение запросов окна выбора объектов - какой вообще смысл этого функционала? - если настройка скрипта - одна (одна процедура) на весь выбор объектов (Общие параметры БД) на все сохраненные запросы, пусть расширенная и оптимизированная скриптом - но по прежнему одна на всех...
что-то я не понимаю всей прелести такого подхода- или тут еще что-то есть интересное и где-то можно оперативно переключать/выбирать ту или иную процедуру скрипта - какой-то выпадающий список или что-то еще?

_________________

Софт - RicCRM<<LotsiaPDM(4.40)<<MsSQL(5/8)
Уровень администрирования - Альтернативный



Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 28 июн 2010, 08:21 
Не в сети
Активный участник
Аватара пользователя

Зарегистрирован: 15 июл 2004, 15:12
Сообщения: 420
Откуда: Подольск
Благодарил (а): 8 раз.
Поблагодарили: 2 раз.
Цитата:
у меня на msgbox как таковой ругается

Не работают здесь диалоговые окна.
Цитата:
что-то я не понимаю всей прелести такого подхода- или тут еще что-то есть интересное и где-то можно оперативно переключать/выбирать ту или иную процедуру скрипта - какой-то выпадающий список или что-то еще?

Создавайте служебные атрибуты, не привязанные к типам объектов, с редактированием "список", добавляйте в них нужные Вам значения. Обрабатывайте эти атрибуты отдельно от остальных. Вот и будут Вам выпадающие списки и иные процедуры скрипта. А вообще, рекомендую определиться: а зачем конкретно Вам нужны собственные поисковые процедуры? Глядишь под конкретную задачу и решение найдется... Мне например, LSQuery очень пригодился для оптимизации скорости поиска, т.к. некоторые варианты поиска с большим количеством атрибутов и, особенно, с условием ИЛИ у меня отрабатывали за десятки секунд, а сейчас менее секунды.

_________________
Ах и с ними невозможно
И без них никак нельзя


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 28 июн 2010, 09:15 
Не в сети
Активный участник
Аватара пользователя

Зарегистрирован: 24 авг 2006, 08:06
Сообщения: 1646
Откуда: 55.745578,37.665825
Благодарил (а): 8 раз.
Поблагодарили: 3 раз.
Цитата:
Создавайте служебные атрибуты, не привязанные к типам объектов, с редактированием "список", добавляйте в них нужные Вам значения.
не вопрос, а выбор визуальный как сделать? что я хочу такой алгоритм/процедуру(функцию) скрипта - поиска применить или такой или не применять вообще....
весь вопрос именно в этом

если скрипт нужен просто для оптимизации поиска ввиду загруженности разработчика - Лоция дала инструмент - ты на его основе сделал работу по оптимизации
Цитата:
Мне например, LSQuery очень пригодился для оптимизации скорости поиска
- и Лоция может включить твой код в базовую поставку - это одно. Просто общая процедура для всей базы сделанная клиентом. По аналогии с DBPrint.

или есть какое то специализированное применение скрипта при выборе объекта с привязкой не к одному методу поиска а к нескольким - с возможностью выбора? Может можно создать несколько Именованных Окон выбора со своими скриптами - по аналогии с Именованной Подборкой?
Типа -это окно выбора - умеет хорошо отбирать дочерние объекты, а это просто делать поиск по базе без привязкам к иерархии... вот в этом плане

_________________

Софт - RicCRM<<LotsiaPDM(4.40)<<MsSQL(5/8)
Уровень администрирования - Альтернативный



Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 28 июн 2010, 10:03 
Не в сети
Активный участник
Аватара пользователя

Зарегистрирован: 15 июл 2004, 15:12
Сообщения: 420
Откуда: Подольск
Благодарил (а): 8 раз.
Поблагодарили: 2 раз.
1. Создаем строковые атрибуты "Параметр поиска 1" и "Параметр поиска 2" и т.д. Редактирование "список". В список значений добавляем все возможные варианты этих параметров.
2. В поисковом скрипте анализируем наличие в условиях поиска атрибутов из п.1. Если их нет, то идем по некоему варианту "по умолчанию". Если какие-то значения параметра поиска установлены, то анализируя их значения, активируем те или иные функции и алгоритмы поиска.
3. А теперь по использованию атрибутов-параметров поиска
3.1. Если пользователю нужно самому выбрать параметр поиска, то создаем поисковую форму (если опыта с поисковыми формами нет, почитайте хелп и поэкспериментируйте), в которой помимо атрибутов искомых объектов добавляем атрибуты-параметры, созданные на шаге 1.
3.2. Если нужно жестко задать некий вариант поиска, указываем в условиях отбора объекта нужное значение атрибута-параметра и пользователь знать о нем не будет ничего и изменить его не сможет.

В п.1.-3. вроде как все визуально и применимо для большинства реальных потребностей.

Пример применения такого подхода мы уже обсуждали в viewtopic.php?f=18&t=631

Цитата:
Может можно создать несколько Именованных Окон выбора со своими скриптами - по аналогии с Именованной Подборкой?

В документации Именованные Окна выбора называются формами поиска. Далее см. выше.

Цитата:
если скрипт нужен просто для оптимизации поиска ввиду загруженности разработчика - Лоция дала инструмент - ты на его основе сделал работу по оптимизации

Мне кажется, что реализация моего оптимизированного варианта поиска заняла бы у Лоции Софт гораздо меньше времени, чем разработка LSQuery. Хотя, конечно, Вы можете со мной не согласиться - на то и холивар.

Цитата:
Типа -это окно выбора - умеет хорошо отбирать дочерние объекты, а это просто делать поиск по базе без привязкам к иерархии... вот в этом плане

Судя по всему, опыт организации поиска объектов стандартными средствами Лоции у Вас не очень большой... На мой взгляд, поиск Лоции - это одна из сильных ее сторон, насколько я могу судить по шапочному знакомству с некоторыми из ее конкурентов.

_________________
Ах и с ними невозможно
И без них никак нельзя


Вернуться к началу
 Профиль  
Ответить с цитатой  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 8 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 3


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
cron
Создано на основе phpBB® Forum Software © phpBB Group
Русская поддержка phpBB