Openedge Progress 4GL Table join

какие-либо советы от гуру по развитию 4GL взглянуть на блок кода 4GL, приведенный ниже, и посмотреть, не слишком ли это сделано? можно ли сделать так, чтобы было легче следить / было легче читать?

У меня есть TblA

Report  
6998077 
6998078 
6998097 
7062816 

И TblB

+-----------+------------+-----------+
| ID        |      Source|    Report |
+-----------+------------+-----------+
|   4976117 |    6998077 |   6998077 |
|   4976118 |    6998078 |   6998078 |
|   4976137 |    6998097 |   6998097 |
|   5107798 |    7062816 |   6998078 |
|   5107799 |    7062816 |   6998097 |
+-----------+------------+-----------+

и у меня, на мой взгляд, сложный цикл Progress 4GL:

def temp-table TblTemp no-undo
field cTypeOfRec     as char
field Report         as int
field Source         as int
field ID             as int 
index key is unique primary Report Source ID.

procedure SOOptimize:
  output stream dOut1 to value("/OutPut.txt").
  export stream dOut1 delimiter "|"
    "Report"
    "Source"  
    "ID".  
  for each TblA no-lock
           on error undo, return error on stop undo, return error:
    for each TblB no-lock where
             TblB.Source = TblA.Report
             on error undo, return error on stop undo, return error:

      find TblTemp exclusive-lock where
           TblTemp.SrcPltSeq = TblA.Report and
           TblTemp.RptPltSeq = TblB.Report and
           TblTemp.ID        = TblB.ID
           no-error.
      if NOT available TblTemp
      then do:
        create TblTemp.
        assign
          TblTemp.cTypeOfRec = "From LoopA"
          TblTemp.SrcPltSeq  = TblA.Report
          TblTemp.RptPltSeq  = TblB.Report
          TblTemp.ID         = TblB.ID.
      end. 
    end.
    for each TblB no-lock where
             TblB.Report = TblA.Report
             on error undo, return error on stop undo, return error:  
      find TblTemp exclusive-lock where
           TblTemp.SrcPltSeq = TblB.Source     and
           TblTemp.RptPltSeq = TblA.Report     and
           TblTemp.ID        = TblB.ID
           no-error.

      if NOT available TblTemp
      then do:
        create TblTemp.
        assign
          TblTemp.cTypeOfRec = "From LoopB"
          TblTemp.SrcPltSeq    = TblB.Source     
          TblTemp.RptPltSeq    = TblA.Report
          TblTemp.ID           = TblB.PltSrcSeq.        
      end.
    end.
  end.
  for each TblTemp no-lock
  on error undo, return error on stop undo, return error:
    export stream dOut1 delimiter "|"
      TblTemp.      
  end.  
end procedure.

Тогда результат моего кода прогресса:

+------------+---------+---------+---------+
| cTypeOfRec | Source  | Report  |   ID    |
+------------+---------+---------+---------+
| From LoopA | 6998077 | 6998077 | 4976117 |
| From LoopA | 6998078 | 6998078 | 4976118 |
| From LoopB | 7062816 | 6998078 | 5107798 |
| From LoopA | 6998097 | 6998097 | 4976137 |
| From LoopB | 7062816 | 6998097 | 5107799 |
+------------+---------+---------+---------+

У меня очень ограниченные знания о Progress 4GL. Этот код кажется чрезмерно готовым? может быть проще?

Я исхожу из фона SQL. Таким образом, в SQL я могу решить эту проблему довольно быстро и легко. Под этим я подразумеваю, что ВСЕ этот блок выполнения кода в основном просто говорит: «Из LoopA», если NULL в LoopB, в противном случае - «из LoopB».

Вот эквивалент SQL, который я придумал:

Select 
case when B.ID is null then 'From LoopA'  
else B.cTypeOfRec 
End "cTypeOfRec"
, A.*  
from #TblTemp A 
left join (
    select A.*, 'From LoopB'  "cTypeOfRec" from ( select * from #TblTemp)A
    left join (
        select B.Source, A.Report, B.ID  from #TblA A
        Inner join #TblB B
        on B.Report=A.Report)B
    on A.Source = B.Report
    where B.Source is null) B
on A.Report=B.Report
and a.ID = b.ID 
and a.Source= b.Source
order by A.Report
, case when B.ID is null then 'From LoopA'  
else B.cTypeOfRec 
End

какие-либо советы от гуру прогресса 4GL взглянуть на блок кода 4GL выше и посмотреть, не слишком ли это сделано? можно ли сделать так, чтобы было легче следить / читать?

Но я открыт для любого ответа, если это правильный способ кодирования в 4GL для достижения конечного результата, тогда я в порядке.

Спасибо Спасибо


person BobNoobGuy    schedule 28.02.2017    source источник


Ответы (2)


Кажется, вы дважды проходите через TblA и TblB. Вместо этого создайте TblTemp для каждого TblB. Затем просмотрите TblA, чтобы увидеть, соответствует ли он записи TblTemp. Вы можете переместить логику временной таблицы в отдельную процедуру.

def temp-table TblTemp no-undo
field cTypeOfRec     as char
field RptPltSeq      as int
field SrcPltSeq      as int
field ID             as int 
index key is unique primary RptPltSeq SrcPltSeq ID.

define stream dOut1.

run SOOptimize.

procedure SOOptimize:
  output stream dOut1 to value("OutPut.txt").
  export stream dOut1 delimiter "|"
    "Report"
    "Source"  
    "ID".  

  for each TblB no-lock:
    run updateTempRec (input "From LoopB", input TblB.Source, input TblB.Report, input TblB.ID). 
  end.

  for each TblA no-lock:
    run updateTempRec (input "From LoopA", input TblA.Report, input TblA.Report, input 0).      
  end.

  for each TblTemp no-lock:
    export stream dOut1 delimiter "|"
      TblTemp.      
  end.  
end procedure.

procedure updateTempRec:
    define input parameter pcType as character no-undo.
    define input parameter piSrc as integer no-undo.
    define input parameter piRpt as integer no-undo.
    define input parameter piID as integer no-undo.

    find first TblTemp where
      TblTemp.SrcPltSeq  = piSrc and
      TblTemp.RptPltSeq = piRpt
      no-error.

    if available(TblTemp) then
      TblTemp.cTypeOfRec = pcType.
    else
      if piID <> 0 then
      do:
        create TblTemp.

        assign
          TblTemp.cTypeOfRec = pcType
          TblTemp.SrcPltSeq  = piSrc     
          TblTemp.RptPltSeq  = piRpt
          TblTemp.ID         = piID.
      end.
end procedure.
person TheDrooper    schedule 28.02.2017

Вы могли бы написать что-то вроде следующего

for each TblA no-lock,
  each TblB no-lock where
           TblB.Source = TblA.Report
        or TblB.Report = TblA.Report
           on error undo, return error on stop undo, return error:
  /* ... */
end.

Я не знаю, помогает ли это уже, т.е. если бы вы могли пропустить временную таблицу. По крайней мере, для одной записи TblA вы не должны видеть одну и ту же запись TblB дважды (в противном случае это произошло бы для записей с TblB.Source = TblB.Report). Если я заменю TblA.Report на TblB.Source в первых for each TblB и TblA.Report на TblB.Report, тогда единственными различиями будут TblTemp.cTypeOfRec и TblTemp.ID, так что вы сможете сократить код.

person idspispopd    schedule 31.03.2017