Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Web программирование > SQL, базы данных
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 05.12.2017, 11:26   #1
Hatefulforums
Новичок
Джуниор
 
Регистрация: 05.12.2017
Сообщений: 2
По умолчанию Помогите с запросом

Уважаемые товарищи, здравствуйте! У меня возникла проблема, которую я сам, к сожалению, решить не могу...
Опишу задачу стоящую пред мной:
Есть две таблицы.
Первая с данными о заказах(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.
Изображения
Тип файла: jpg Польз.окно.jpg (30.7 Кб, 123 просмотров)
Hatefulforums вне форума Ответить с цитированием
Старый 05.12.2017, 11:30   #2
Hatefulforums
Новичок
Джуниор
 
Регистрация: 05.12.2017
Сообщений: 2
По умолчанию

У меня есть некоторые наработки, но никак не могу дойти до полного решения...
Вот некоторые варианты:
1. Использование табличной переменной (но мне не нравится)

Код:
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
2. А вот мне больше нравится, но тоже не могу до ума довести

Код:
SELECT          
 T.PrdZkg_Dt,
 T.PrdZkg_Rcd,
 T.PrdZkg_Nmr,
 T.PrdZkg_RcvrID,
 T.PrdZkg_RcvrNm,
 T.PrdZkg_Sm,
 S.SklNk_TMNet
  
   LAG(T.PrdZkg_Dt) OVER(PARTITION BY T.PrdZkg_RcvrID
                          ORDER BY T.PrdZkg_Dt, T.PrdZkg_Rcd) AS PredDt,
   LAG(T.PrdZkg_Nmr) OVER(PARTITION BY T.PrdZkg_RcvrID
                          ORDER BY T.PrdZkg_Dt, T.PrdZkg_Rcd) AS PredNmr,
   LAG(S.SklNk_TMNet) OVER(PARTITION BY T.PrdZkg_RcvrID
                          ORDER BY T.PrdZkg_Dt, T.PrdZkg_Rcd) AS PredVes
   LAG(T.PrdZkg_Sm) OVER(PARTITION BY T.PrdZkg_RcvrID
                          ORDER BY T.PrdZkg_Dt, T.PrdZkg_Rcd) AS PredSm                                                                                                                                                                                                                                                                                                                                                                                                                                                   
FROM PrdZkg T   
  LEFT JOIN SklNk S ON T.PrdZkg_Rcd = S.SklNk_RcdZkg
WHERE T.PrdZkg_Dt = :dds AND T.PrdZkg_RcvrID = :kkg
 
ORDER BY T.PrdZkg_Dt DESC
Hatefulforums вне форума Ответить с цитированием
Старый 05.12.2017, 11:57   #3
Sciv
Старожил
 
Аватар для Sciv
 
Регистрация: 16.05.2012
Сообщений: 3,211
По умолчанию

В дельфи всё присвоение делайте:

Код:
Zaprs.SQL.Text := 'Ваш запрос без грузополучателя';
if Грузополучатель выбран then 
begin
  Zaprs.SQL.Text := Zaprs.SQL.Text + ' AND условие отбора по грузополучателю';
  Zaprs.ParamByName('kkg').datatype := ftInteger;
  Zaprs.ParamByName('kkg').value := kgRcd;  
end;
Zaprs.ParamByName('dds').datatype := ftDate;
Zaprs.ParamByName('dds').value := DateEdit1.Date;
Zaprs.Open;
Начал решать проблему с помощью регулярных выражений. Теперь решаю две проблемы...
Sciv вне форума Ответить с цитированием
Старый 05.12.2017, 12:07   #4
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 19,042
По умолчанию

Тоже за вариант от Sciv. Можно и в запросе конечно, что нибудь типа такого:
Код:
where (T1.PrdZkg_Dt = :dds) and ((T1.PrdZkg_RcvrID = :kkg) or (0 = :kkg))
и передавать 0 в kkg, если не задан грузополучатель. Но эффективность запроса упадет. Понятно в предположении что id грузополучателя не бывает нулем ))
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Помогите с запросом Nastiya SQL, базы данных 1 22.12.2015 20:08
Помогите с запросом FreddyZSX SQL, базы данных 7 07.04.2015 21:52
Помогите с запросом der90 SQL, базы данных 2 13.02.2014 10:50
Помогите с запросом Juries Microsoft Office Access 0 12.04.2009 00:29
помогите с запросом 9-11 БД в Delphi 4 20.11.2006 10:04