JonJon
JonJon

Reputation: 41

Qlikview aggregation

I have a table like the below. For each date there is a have a product. And I want to aggregate by the product and carry forward the total. But the total is limited to 0. For each day and product, I want to aggregate and carry forward the aggregate.

Date product Amount
06/Jan/2021 a 300
05/Jan/2021 a 200
05/Jan/2021 b 500
04/Jan/2021 a -100
04/Jan/2021 b 1100
03/Jan/2021 a -500
03/Jan/2021 b -900
02/Jan/2021 a 200
02/Jan/2021 b 500
01/Jan/2021 a 100

For the latest date I want to see the output as below:

Date product total
06/Jan/2021 a 500
06/Jan/2021 b 1600

Upvotes: 1

Views: 203

Answers (1)

Stefan Stoychev
Stefan Stoychev

Reputation: 4987

Check out the script below. Ive annotated the code to explain each step.

If you reload the script the result table will be:

TotalAmount table

The basic idea is:

  • order the records by product and date (ascending)
  • while loading the ordered table aggregate the records (by product)
  • if the sum is < 0 then return 0, else continue with the aggregation
  • once we have the aggregation find the max date for each product and flag these records. The max date record will contain the total amount (per product)
  • filter the flagged records and load them in the final table

Annotated load script:

RawData:
Load * inline [
Date       , product, Amount
06/Jan/2021, a      , 300
05/Jan/2021, a      , 200
05/Jan/2021, b      , 500
04/Jan/2021, a      , -100
04/Jan/2021, b      , 1100
03/Jan/2021, a      , -500
03/Jan/2021, b      , -900
02/Jan/2021, a      , 200
02/Jan/2021, b      , 500
01/Jan/2021, a      , 100
];

NoConcatenate

// Order the data by product and date in ascending order
OrderedData:
Load
  date(date#(Date, 'DD/MMM/YYYY')) as Date, // convert to date
  product,
  Amount
Resident 
  RawData
Order By 
  product,
  Date asc
;

// we dont need RawData table anymore
Drop Table RawData;

// CalculatedAmount calculation/logic:
// * if the current value for product is not equal to the prvious value
//   get the current amount. This the case where the producs are "switched"
// * if the sum of the current Amount value + the previous CalculatedAmount value
//   is less than 0 then return 0
// * for the rest of the cases - return the aggregated amount - current Amount
//   added to the previous CalculatedAmount
CalculatedAmount:
Load 
  Date,
  product,
  Amount,
  if( product <> peek('product'), Amount,
    if( Amount + peek('CalculatedAmount') < 0, 0,
  Amount + peek('CalculatedAmount')
  )) as CalculatedAmount
Resident 
  OrderedData
;

// we dont need OrderedData anymore
Drop Table OrderedData;

// use the CalculatedAmount table to find the max date for each product
// these records are containing the total amount for each product
// flag these records with 1 and join the result table back to
// CalculatedAmount table
join (CalculatedAmount)
Load 
  max(Date) as Date,
  product,
  1 as isTotalAmount
Resident
  CalculatedAmount
Group By 
  product
;

// the final table - filter CalculatedAmount table to return
// only the records for which isTotalAmount = 1
TotalAmount:
Load 
  Date,
  product,
  CalculatedAmount as TotalAmount
Resident
  CalculatedAmount
Where
  isTotalAmount = 1
;

// we dont need CalculatedAmount table anymore
Drop Table CalculatedAmount;

Upvotes: 2

Related Questions