Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Помогите с запросом  [new]
HatefulForums
Member

Откуда:
Сообщений: 3
Вообщем штука такая:
Есть две таблицы.
Первая с данными о заказах(PrdZkg):

PrdZkg_Dt - дата заказа
PrdZkg_Nmr - номер заказа
PrdZkg_Rcd - уникальный код заказа
PrdZkg_RcvrID - ID грузополучателя
PrdZkg_RcvrNm - наименование грузополучателя
PrdZkg_Sm - сумма заказа в руб

Вторая таблица(SklNk) - в ней вес заказа( поле SklNk_TMNet)

Задача такая:
Вывести в отчете(FastReport) в одном MasterData, в строку, поля:
Дата текущего заказа (за выбранное число); номер текущего заказа; ID грузополучателя; наименование грузополучателя; вес текущего заказа; сумму текущего заказа; дату предыдущего заказа; номер предыдущего заказа; вес предыдущего заказа; сумму предыдущего заказа.
И загвоздка в том, что есть пользовательское окно(в приложенном файле).
Так вот, если выбирается дата и грузополучатель, то все отлично выводиться.
А во втором случае, если выбирается дата, но не выбирается грузополучатель, он должен выводить просто все заказы по всем грузополучателям за выбранную дату и их предыдущие заказы. Тут как бы тоже все работает, но я сделал это настолько не эстетично, что мне хотелось бы узнать - как можно на SQL языке переписать мой код, где я циклом перебираю и запиливаю во временную таблицу...
Код прилагаю. Буду очень благодарен за помощь, наставления, советы и критику.

Вот три мои запроса:
1.(frst)
select                     
PrdZkg_Dt
,PrdZkg_Nmr
,PrdZkg_Rcd    
,PrdZkg_RcvrID
,PrdZkg_RcvrNm
,PrdZkg_Sm
,SklnK.SklnK_TMNet    
from PrdZkg
left join SklnK on PrdZkg_Rcd = SklnK_RcdZkg
where PrdZkg.PrdZkg_Dt = :dds

2.(sec)
select TOP 1                    
PrdZkg_Dt
,PrdZkg_Nmr
,PrdZkg_Rcd    
,PrdZkg_RcvrID
,PrdZkg_RcvrNm
,PrdZkg_Sm
,SklnK.SklnK_TMNet    
from PrdZkg
left join SklnK on PrdZkg_Rcd = SklnK_RcdZkg
where PrdZkg.PrdZkg_Dt < :dds and PrdZkg.PrdZkg_RcvrID = :kkg
order by PrdZkg_Dt desc

3.(Zaprs)
select TOP 1
  ZprP.PrdZkg_Dt
 ,ZprP.PrdZkg_Nmr
 ,ZprP.PrdZkg_Sm
 ,SklNK.SklNk_TMNet
 ,ZprT.PrdZkg_DtT  
 ,ZprT.PrdZkg_NmrT  
 ,ZprT.PrdZkg_RcdT  
 ,ZprT.PrdZkg_RcvrIDT  
 ,ZprT.PrdZkg_RcvrNmT  
 ,ZprT.PRdZkg_SmT
 ,ZprT.SklNk_TMNetT                                                       
from PrdZkg ZprP
 left join SklNk on ZprP.PrdZkg_Rcd = SklNk_RcdZkg
 left join             
   (select                 
      ZprT2.PrdZkg_Dt as PrdZkg_DtT                              
     ,ZprT2.PrdZkg_Nmr as PrdZkg_NmrT                                
     ,ZprT2.PrdZkg_Rcd as PrdZkg_RcdT                             
     ,ZprT2.PrdZkg_RcvrID as PrdZkg_RcvrIDT                                   
     ,ZprT2.PrdZkg_RcvrNm as PrdZkg_RcvrNmT                                   
     ,ZprT2.PrdZkg_Sm as PrdZkg_SmT                           
     ,SklNk.SklNk_TMNet as SklNk_TMNetT                                 
   from PrdZkg as ZprT2
   left join SklNk on ZprT2.PrdZkg_Rcd = SklNk_RcdZkg
        where ZprT2.PrdZkg_Dt = :dds and ZprT2.PrdZkg_RcvrID = :kkg) 
        ZprT on ZprP.PrdZkg_RcvrID = ZprT.PrdZkg_RcvrIDT
where ZprP.PrdZkg_Dt < :dds and ZprP.PrdZkg_RcvrID = :kkg
order by ZprP.PrdZkg_Dt desc


А вот сам код:

var kgRcd : string;
    ii : integer;
procedure OkBtnOnClick(Sender: TfrxComponent);
begin
  if Label4.Caption <> '' then begin
     ii := 1;
    Zaprs.Close;
    Zaprs.ParamByName('dds').datatype := ftDate;
    Zaprs.ParamByName('dds').value := DateEdit1.Date;
    Zaprs.ParamByName('kkg').datatype := ftInteger;
    Zaprs.ParamByName('kkg').value := kgRcd;
    Zaprs.Open;
    end
  else begin
    ii := 2;
    frst.Close;
    frst.ParamByName('dds').datatype := ftDate;
    frst.ParamByName('dds').value := DateEdit1.Date;
    frst.open;
    frst.First;
    while not frst.eof do begin
      sec.Close;
      sec.ParamByName('dds').datatype := ftDate;
      sec.ParamByName('dds').value := DateEdit1.Date;
      sec.ParamByName('kkg').datatype := ftInteger;
      sec.ParamByName('kkg').value := (<frst."PrdZkg_RcvrID">);
      sec.open;
      Tmp1.Append;
      Tmp1.FieldByName('DatTek').value := <frst."PrdZkg_Dt">;
      Tmp1.FieldByName('Nm').value := <frst."PrdZkg_Nmr">;
      Tmp1.FieldByName('Cod').value := <frst."PrdZkg_RcvrID">;
      Tmp1.FieldByName('NmGp').value := <frst."PrdZkg_RcvrNm">;
      Tmp1.FieldByName('VesTek').value := <frst."SklnK_TMNet">;
      Tmp1.FieldByName('SumTek').value := <frst."PrdZkg_Sm">;
      Tmp1.FieldByName('DatPr').value := <sec."PrdZkg_Dt">;
      Tmp1.FieldByName('NmPr').value := <sec."PrdZkg_Nmr">;
      Tmp1.FieldByName('VesPr').value := <sec."SklnK_TMNet">;
      Tmp1.FieldByName('SumPr').value := <sec."PrdZkg_Sm">;
      Tmp1.Post;
      frst.Next;
      end;
  end;
  if ii=1 then begin
    if(Zaprs.isEmpty) then
    begin
      ShowMessage('Отчет пуст');
      StopCloseReport;
    end;
  end;
  if ii=2 then begin
    if(frst.isEmpty) then
    begin
      ShowMessage('Отчет пуст');
      StopCloseReport;
    end;
  end;
end;

procedure DialogPage1OnShow(Sender: TfrxComponent);
begin

  //  DateEdit1.Date:=now;



end;

procedure CancelBtnOnClick(Sender: TfrxComponent);
begin
  StopCloseReport;
end;

procedure MasterData1OnBeforePrint(Sender: TfrxComponent);
begin

end;



procedure Button1OnClick(Sender: TfrxComponent);
var kgNm : string;
begin

  BPRO.SPR_OPEN_DLG(1, 2);
  kgRcd := BPRO.SPR_OPEN_GETID();
  kgNm := BPRO.SPR_OPEN_GETNM();
  Label4.Caption := kgNm+ '  '+datetostr(DateEdit1.Date);

end;


procedure Memo14OnBeforePrint(Sender: TfrxComponent);
var ttmp: real;
begin
  if ii=1 then begin
  if (<Zaprs."SklNk_TMNetT">) > (<Zaprs."SklNk_TMNet">) then begin
    ttmp := BPRO.BP_ROUND((<Zaprs."SklNk_TMNetT">) - (<Zaprs."SklNk_TMNet">),2);
    Memo14.Text := 'Вес заказов увеличился на '+ FloatToStr(ttmp) + ' кг';
   end
  else begin
    ttmp := BPRO.BP_ROUND((<Zaprs."SklNk_TMNet">) - (<Zaprs."SklNk_TMNetT">),2);
    Memo14.Text := 'Вес заказов уменьшился на '+ FloatToStr(ttmp) + ' кг';
  end;
 end;
end;

begin
 Tmp1.addfield('DatTek', 'DATE', 8);
 Tmp1.addfield('Nm', 'STRING', 50);
 Tmp1.addfield('Cod', 'STRING', 8);
 Tmp1.addfield('NmGp', 'STRING', 300);
 Tmp1.addfield('VesTek', 'FLOAT', 10);
 Tmp1.addfield('SumTek', 'FLOAT', 10);
 Tmp1.addfield('DatPr', 'DATE', 8);
 Tmp1.addfield('NmPr', 'STRING', 50);
 Tmp1.addfield('VesPr', 'FLOAT', 10);
 Tmp1.addfield('SumPr', 'FLOAT', 10);
 Tmp1.createdataset;

end.


К сообщению приложен файл. Размер - 30Kb
23 ноя 17, 06:59    [20976742]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом  [new]
HandKot
Member

Откуда: Sergiev Posad
Сообщений: 2979
HatefulForums, по-моему Вам надо просто в запросе сделать проверку на NULL значение

where PrdZkg.PrdZkg_Dt < :dds and PrdZkg.PrdZkg_RcvrID = :kkg

where PrdZkg.PrdZkg_Dt < :dds and (PrdZkg.PrdZkg_RcvrID = :kkg or :kkg Is Null)


и в коде что-то типа (в дельфи не работаю, пишу алгоритм)
Zaprs.ParamByName('kkg').value := iif(Label4.Caption <> '', kgRcd, DBNull);

но Ваше решение, мне кажется, лучше
23 ноя 17, 07:49    [20976770]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом  [new]
HatefulForums
Member

Откуда:
Сообщений: 3
С проверкой на Null не получиться, ибо тогда запрос, вместо того, чтобы вывести все заказы, выдает пустой отчет.
А вот по-поводу, что у меня лучше вышло - тут штука-то в том, что с одной стороны вышло весьма надежно, но создание временной таблицы и цикл дают большую нагрузку на сеть, чем если бы все три запроса были объединены в один...

P.S: чувствую что можно решить и без всей моей "катавасии" и что пора освежать в памяти знания о Join'ах, ибо складывается ощущение, что задачка то простецкая, но решение всегда ускользает из поля зрения...
23 ноя 17, 08:15    [20976790]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом  [new]
Nickolay-123
Member

Откуда:
Сообщений: 21
HatefulForums,

where ZprP.PrdZkg_Dt < :dds and ZprP.PrdZkg_RcvrID = isnull(:kkg, ZprP.PrdZkg_RcvrID)
23 ноя 17, 08:41    [20976820]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом  [new]
asdor
Member

Откуда: Москва
Сообщений: 484
HatefulForums,
Наверное стоит получать все одним запросом.
С клиента посылать нужные условия.
кажется что то типа
select                     
 p.Dt
,P.Nmr
,P.Rcd    
,P.RcvrID
,P.RcvrNm
,P.Sm
,S.SklnK_TMNet,
lag(P.Nmr) OVER(PARTITION BY P.RcvrID
                 ORDER BY p.Dt, P.Rcd) AS prevNmr,    
lag(P.sm) OVER(PARTITION BY P.RcvrID
                 ORDER BY p.Dt, P.Rcd) AS prevsm,    
lag(S.SklnK_TMNet) OVER(PARTITION BY P.RcvrID
                 ORDER BY p.Dt, P.Rcd) AS prevWeigth    
from PrdZkg P
	left join SklnK S 
	on P_Rcd = S_RcdZkg

в условиях либо добавляете фильтрацию по заказчику, либо нет (мне показалось, что запрос вы формируете на клиенте, потому это легко)
Всегда получаете, одну структуру множества, и легко выводится в один и тот же отчет.
Код клиента, упрощается серьезно.
23 ноя 17, 08:55    [20976844]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом  [new]
HatefulForums
Member

Откуда:
Сообщений: 3
asdor, я вообще подумываю использовать табличную переменную, но не могу понять как...
Получилось что-то типа такого:
declare @tbldn table (rcdzk bigint, rcdgpl bigint)

insert into @tbldn (rcdzk, rcdgpl)
select 
max(T3.PrdZkg_Rcd) as PrdZkg_rcd,
T3.PrdZkg_RcvrID
from PRDZKG T3
where (T3.PrdZkg_Dt < :dds) and (T3.PrdZkg_RcvrID = :kkg)                     
group by  T3.PrdZkg_RcvrID

select
T1.PrdZkg_Rcd,
T1.PrdZkg_RcvrID,
T1.PrdZkg_Dt
,z2.PrdZkg_Nmr
,z2.PrdZkg_Dt  
from PRDZKG T1
left join @tbldn dt on dt.rcdgpl=T1.PrdZkg_RcvrID
left join PRDZKG z2 on  z2.PrdZkg_Rcd=dt.rcdzk

where (T1.PrdZkg_Dt = :dds) and (T1.PrdZkg_RcvrID = :kkg)                              

order by 2

Но совсем не понимаю, как туда все остальное напихать...
4 дек 17, 09:40    [21003150]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить