2016-09-25 2 views
1

AS400의 LAG 및 LEAD 구문은 무엇입니까? 이전 레코드를 기반으로 현재 레코드에 대한 계산을 수행하려고합니까?이전 레코드의 사용 된 데이터로 현재 레코드의 데이터 계산

예 : 이전 레코드를 기준으로 각 레코드의 작업 센터 수량을 계산해야합니다.

enter image description here

UPDATE : I가 계산 아니지만 이전 행의 합계에 이전 행에 기초되도록 상기 예에서 설명한 바와 같이

이것은 중요하다. 방금 전 요구 사항에 대해 매우 최적화 된 예제를 제공했지만 이전 레코드의 합계를 빼는 것은 저를 도와주지 못합니다. 이전 기록만을 구독하는 방법이 있습니까?

+0

가하는 방법이 있나요 이전 레코드를 식별하는 데 사용할 수있는 데이터 또는 기본 키의 순서? – rbr94

+0

내 생각에, 이것은 거의 비슷합니다 - http://stackoverflow.com/questions/32066074/how-to-add-and-subtract-value-from-previous-rows-based-on-condition –

+0

@ AT-2016, 이것은 SQL 서버용입니다. 그것이 나를 위해 작동하는지 확실하지 않습니다. – ehh

답변

1

DB2 recursive UDF Table에 대한 나의 답장과 매우 ​​흡사하지만이 답장을 통해 주어진 샘플 데이터 [예상 출력에 대한 동등성을 시각적으로 표현하기위한 열을 더한 결과]을 제외하고는 거의 리뷰를 작성하지 않았습니다. 확인합니다 :

설정 :

set current schema <whatever> 
create table wc 
(work_center for wc  char  
, total_quantity for tq  dec  
, scrap_quantity for sq  dec  
, vfy_quantity for vq  dec 
) 
; 
insert into wc  values  
    ('A' , 1000,  10, 990) 
, ('B' , 1000,  5, 985) 
, ('C' , 1000,  12, 973) 
, ('D' , 1000,  1, 972) 
; 

쿼리 및 결과 :

with 
    ordRows (rn, wc, tq, sq, vq) as 
    (select row_number() over(order by wc) as rn 
      , wc, tq, sq, vq 
    from wc 
    )  
, subRows (rn, wc, tq, sq, vq, cq /* calc qty */) as 
    (select rn, wc, tq, sq, vq 
      , (tq - sq) 
    from ordRows 
    where rn = 1 
    union all 
    select b.rn, b.wc, b.tq, b.sq, b.vq   
      , (a.cq - b.sq) 
    from subRows a 
    join ordRows b 
     on a.rn = (b.rn - 1) 
    ) 
select dec(rn, 5) as rn, wc, tq, sq 
    , vq, ' = ' as eq, cq 
from subrows 
; -- likeness of report from above query: 
....+....1....+....2....+....3....+....4....+....5....+ 
    RN WC  TQ  SQ  VQ EQ   CQ 
    1 A 1,000  10  990 =   990 
    2 B 1,000  5  985 =   985 
    3 C 1,000  12  973 =   973 
    4 D 1,000  1  972 =   972 
******** End of data ********       
+0

"SQL0206 - 열 VQ가 지정된 테이블에 없습니다." 오류 – ehh

+0

이상합니다. 이 스크립트는 각 IBM i 6.1, 7.1, 7.3에서 작동합니다. IIRC 구문은 v5r4부터 지원되어야하지만 해당 릴리스 또는 IBM i 7.2 [aka v7r2]에 액세스 할 수는 없습니다. 사용되는 코드 수준에 대한 언급이 없습니다. OP에서 서버를 * AS400 *이라고 부른 것 중 가장 오래된 것 같습니다. :-( – CRPence

+0

나는 틀린 방식으로 테이블을 만들었습니다. (미안합니다.) 다시 시도했는데 매력처럼 작동합니다. 대단합니다! – ehh

4

누적 합계를 계산하려면 LAGLEAD이 반드시 성취하는 데 도움이되지는 않습니다. 이 시도

SELECT t1.*, 
     t1.total_quantity - (SELECT SUM(t2.scrap_quantity) 
          FROM yourTable t2 
          WHERE t2.work_center <= t1.work_center) AS work_center_quantity 
FROM yourTable t1 
ORDER BY t1.work_center 
+0

좋은 해결책으로 보입니다. 시도해보고 싶습니다 – ehh

+0

내 업데이트 – ehh

0

:

with tmp as (
select t.*, rownumber() over(order by work_center ) as rang 
from t) 
select f1.*, 
ifnull(f2.work_center , f1.total_quantity) - f1.scrap_quantity 
AS work_center_quantity 
from tmp f1 left outer join tmp f2 
on f1.rang-1=f2.rang 
+0

을 참조하십시오. 좋은 시작이지만 작동하지 않습니다. 나는 그것을 작동하게하려고 노력하고있다. 첫 번째 레코드 만이 다른 레코드가 비어있는 값을 얻었습니다. – ehh

+0

제안에 대한 조사를 한 결과 이전 계산 된 work_center_quantity를 고려하지 않은 것으로 나타났습니다. 이상적인 방법은 "ifnull ..."을 "ifnull (f2.work_center_quantity, f1.total_quantity) - f1.scrap_quantity AS work_center_quantity"로 바꾸는 것이지만 "work_center_quantity"는 테이블에 존재하지 않습니다. "이상적인"솔루션을 얻을 수있는 방법이 있습니까? – ehh

0

: 그것을 시도

with tmp as (
select t.*, rownumber() over(order by work_center ) as rang 
from t) 
select f1.*, 
f1.total_quantity - f3.sum_scrap_quantity  
AS work_center_quantity 
from tmp f1 
inner join lateral 
(
    select sum(f2.scrap_quantity) sum_scrap_quantity  tmp f2 
    where f2.rang<=f1.rang 
) f3 on 1=1 
2

첫째, 적절한 이름을 사용 누적 합계를 계산하는 방법 중 하나는 상관 하위 쿼리를 사용하는 것입니다 플랫폼을 사용하면 현재 참조 자료를 찾을 확률이 훨씬 높아집니다. IBM i 문서는 Knowledge Center에 있습니다.

둘째, 세 가지 DB2 계열이 있습니다. IBM i 제품군에는 아직 LEAD 및 LAG가 없습니다. (다른 패밀리는 LUW (Linux, Unix, Windows) 및 z - mainframes 용 DB2입니다.)

SQL 세트 처리가 상대 레코드 x 호가 아닌 세트에 집중되는 경향이있어서 요구가 약간 이상합니다. 따라서 단순한 부모/자식 관계가 없기 때문에 재귀 CTE를 사용할 수 없습니다. 그러나, brute force가 적용될 수 있습니다.

create table so (
    WorkCenter char(5), 
    TotalQuantity decimal(7, 0), 
    ScrapQuantity decimal(7, 0), 
    WorkCenterQuantity decimal(7, 0) 
); 

insert into so values ('A', 1000, 10, 990); 
insert into so values ('B', 1000, 5, 985); 
insert into so values ('C', 1000, 12, 973); 
insert into so values ('D', 1000, 1, 972); 

select 1 as level, WorkCenter, TotalQuantity, ScrapQuantity, WorkCenterQuantity, TotalQuantity - ScrapQuantity as newQUantity 
from so 
where rrn(so) = 1 
union all 
select rrn(o) as level, o.WorkCenter, o.TotalQuantity, o.ScrapQuantity, o.WorkCenterQuantity, 
    (select i.WorkCenterQuantity 
    from so i 
    where rrn(i) = rrn(o) - 1) - o.ScrapQuantity as NewWorkCenterQuantity 
from so o 
where rrn(o) > 1 
order by 1; 

아이디어는 현재 행에서 열이 계산 첫 번째 행을 잡아이며, UNION 그 후속 현재 및 이전 행을 모두 사용하여 계산을 사용하여 행한다.

EDIT WorkCenterQuantity가 0이라고 가정합니다. 계산에 @ Tim의 누적 합계를 사용하십시오.

update so 
set WorkCenterQuantity = 0; 

update so u 
set WorkCenterQuantity = (
    select NewWorkCenterQuantity 
    from 
    (select 1 as level, WorkCenter, TotalQuantity, ScrapQuantity, WorkCenterQuantity, TotalQuantity - ScrapQuantity as NewWorkCenterQuantity 
    from so 
    where rrn(so) = 1 
     union all 
    select rrn(o) as level, o.WorkCenter, o.TotalQuantity, o.ScrapQuantity, o.WorkCenterQuantity, 
     (select TotalQuantity 
     from so 
     where rrn(so) = 1) 
     - 
     (select sum(i.ScrapQuantity) 
     from so i 
     where rrn(i) <= rrn(o)) as NewWorkCenterQuantity 
    from so o 
    where rrn(o) > 1 
    ) x 
    where u.WorkCenter = x.WorkCenter) 
; 

개념은 행 N + 1의 누계를 사용하여 계산을 수행하는 것이지만, 행 (1)에서 초기 량 입수.

+0

WorkCenterQuantity는 계산할 열입니다. 작성 테이블에서 계산할 값을 추가하십시오. – ehh

+0

정말 @ Tim의 대답을 원하는 것처럼 보입니다. 이전 행은 모든 행과 마찬가지로 업데이트 이후까지 0이 될 것이기 때문에 계산은 이전 행을 기반으로 할 수 없습니다. 따라서 실제로 원하는 것은 이전 계산을 기반으로 한 계산입니다. 이는 누적 합계입니다. 편집을 참조하십시오. –

+0

우리는 거의 다 왔어. 나는 A (990), B (972), C (972), D (972)를 얻고있다. 나는 또한 그것을 고치려고 노력할 것이다. – ehh