Do not input private or sensitive data. View Qlik Privacy & Cookie Policy.
Skip to main content

Announcements
Qlik Open Lakehouse is Now Generally Available! Discover the key highlights and partner resources here.
cancel
Showing results for 
Search instead for 
Did you mean: 
Not applicable

function below(sum(x),A,B) make all arguments calculated

Hello there,

my first thread on this community - pls be patient if I,m not precisely thx

im trying to get things work with this function. In QV help is written: below(sum(value1),1,3) lets you look back to previous 3 rows on load statement and sum value1 from this previous 3 row and insert this sum to current row.

Argument "3" is static. Ist there any trick to make this argument calculable in my case depending on values in previous rows?

Let say we have a table with dates sorted ascending but they appear not day after day. For each day we have no. of sold cars.

dateno. Sold cars
2011-04-012
2011-04-034
2011-04-061
2011-06-075
2011-06-084
2011-06-133
2011-06-152
2011-06-164
2011-06-195


based on this table i`d like to add 2 extra columns that stores info about avg sum. of sold cars in previous 7 days and 14 days from current date in row. It can looks like below:

dateno. Sold cars7 days back from current day14 days back from current day
2011-04-01222
2011-04-03466
2011-04-06177
2011-04-0751212
2011-04-0841416
2011-04-1031319
2011-04-1221521
2011-04-1341825
2011-04-1551428

and on date 2011-04-15 for 14 days back sold 4+1+5+4+3+2+4+5 = 28 cars, and  2011-04-12 for 7 days back sold 1+5+4+3+2 = 15

to sum no of cars function below shoud look back deeper in previous row only if date in that row is not older than 7/14 days from date from current row

it has to be calulated while load script in code, not in layout layer (pivot, set analysis ...).

thanks for your tips.

7 Replies
Not applicable
Author

Hi nowaitaka,

You could create a link between the table containing # of cars sold and a calendar date such as below:

CarsSold:

load * Inline

[

CalendarDate,no. Sold cars

2011-04-01,2

2011-04-03,4

2011-04-06,1

2011-06-07,5

2011-06-08,4

2011-06-13,3

2011-06-15,2

2011-06-16,4

2011-06-19,5

];

Dates:

load * inline

[

CalendarDate

2011-04-01

2011-04-02

2011-04-03

2011-04-04

2011-04-05

...

...

...

2011-06-26

2011-06-27

2011-06-28

2011-06-29

2011-06-30

];

Create a straight table and use the following dimensions:

  • Calendar date

Use the following Expressions to get sum of sales starting N days before the date in the row through the date in the row:

  • sum([no. Sold cars])
  • RangeSum(above(sum([no. Sold cars]), 0, 7))
  • RangeSum(above(sum([no. Sold cars]), 0, 14))

You could swap above with below to get the sum of sales starting the date in the row and ending after N calendar days.You probably don't even need sum function in the last 2 expressions.

John has answered a similar question about everyday sum of past 5 days.

Message was edited by: QueueWeRavn

Not applicable
Author

hi QueueWeRavn,

thx for your tip, this solution works partially.

If U do not make any selections in app that affects the dates, works fine - it takes previous 7/14 rows from stright table where we have days day by day which gives us 1 week and 2 weeks back...

but if U make selection in app that results in excuding some dates (like shops in City1 in last week sold cars only in monday and friday and not in each day) the stright table will show less dates but it`ll calculate expression "RangeSum(above(sum([no. Sold cars]), 0, 7))"  from last 7 rows in this table (but previous 7 rows contains dates that are older than 7 days).

That`s why I was thinking about calculating this expression in data load script to avoid such situation...

My bad is that I didn`t mentioned about this selecions before ....

here is example output from this stright table...

exp1 =RangeSum(above(sum(D_EFECTIVELY_FREE_FIRST_SHORTER_PERIOD), 0, 7))

exp2 =sum(D_EFECTIVELY_FREE_FIRST_SHORTER_PERIOD)

  date                         exp1          exp2

2011-06-0122
2011-06-031614
2011-06-056246
2011-06-0815189
2011-06-1020655
2011-06-1225145
2011-06-15514265
2011-06-17707207
2011-06-1975291
2011-06-22853190
2011-06-2482830
2011-06-2684057
2011-06-29845270

if U tak any date it sums previous 7 rows even if this previous date is older than 7 days (it does not interprets the date - only takes 7 rows back... )

cheers

Not applicable
Author

Hi nowaitaka,

You have a very good point. It would be best to perform such calculations through SQL or other means during loading instead of performing calculations on the fly.

johnw
Champion III
Champion III

I'd suggest the solution in the link that QueueWeRavn posted.  It doesn't require functions like above(), and it doesn't require you to precalculate the values.  It just requires that you build a data model that "understands" what it means to be within the past 7 days or 14 days.  There are more efficient ways to build this data (while loops), but this will probably be fine.

[AsOf]:
LOAD date(fieldvalue('Date',recno())) as "Date"
AUTOGENERATE fieldvaluecount('Date')
;
OUTER JOIN ([AsOf])
LOAD "Date" as "As of Date"
RESIDENT [AsOf]
;
OUTER JOIN ([AsOf])
LOAD * INLINE [
Date Type
Current Day
Rolling 7 Days
Rolling 14 Days
];
INNER JOIN ([AsOf])
LOAD *
RESIDENT [AsOf]
WHERE (   "Date Type"='Current Day'
      AND "Date"="As of Date")
  OR  (   "Date Type"='Rolling 7 Days'
      AND "Date">="As of Date"-7
      AND "Date"<="As of Date")
  OR  (   "Date Type"='Rolling 14 Days'
      AND "Date">="As of Date"-14
      AND "Date"<="As of Date")
;

Then build a pivot table like this:

Dimension 1 = "As of Date"
Dimension 2 = "Date Type" // move to top
Expression  = sum([no. Sold cars])

All of the intelligence is in the data model, which is why the chart itself can be so simple.

Hmmm, let me tack a crack at the while loops approach.

[Dates]:
LOAD date(fieldvalue('Date',recno())) as "Date"
AUTOGENERATE fieldvaluecount('Date')
;
[AsOf]:
LOAD
"Date" as "As of Date"
,'Current Day' as "Date Type"
,"Date"
RESIDENT [Dates]
;
CONCATENATE ([AsOf])
LOAD
"Date" as "As of Date"
,'Rolling 7 Days' as "Date Type"
,date("Date"+1-iterno()) as "Date"
RESIDENT [Dates]
WHILE iterno() <= 7
;
CONCATENATE ([AsOf])
LOAD
"Date" as "As of Date"
,'Rolling 14 Days' as "Date Type"
,date("Date"+1-iterno()) as "Date"
RESIDENT [Dates]
WHILE iterno() <= 14
;
INNER JOIN ([AsOf])
LOAD "Date"
RESIDENT [Dates]
;
DROP TABLE [Dates]
;

Not applicable
Author

Hello,

WHILE statement with iterno() , RecNo() and peek() did the trick in my case . I thought native functions below/above will be the best solution but looks like while statement in LOAD is also optimized in QV so it works good enought for me.

Looks like i have to do some research about good practise while develop model in QV.

Thanks to you both for help, cheers.

Here is my solution from real code (car sale model was only example).

Mytab:

LOAD 

D_DEPARTURE_DATE as D_DEPARTURE_DATE_14 ,

D_DESTINATION as D_DESTINATION_14,

peek('D_EFECTIVELY_FREE_SEATS_14',RecNo()-IterNo(),'DEPARTURESv5') as D_TO_SUM_14

resident DEPARTURESv5

while

(RecNo()-IterNo())>-1 and date(date(D_DEPARTURE_DATE)-13) <= date(peek('D_DEPARTURE_DATE',RecNo()-IterNo(),'DEPARTURESv5')) and D_DESTINATION = peek('D_DESTINATION',RecNo()-IterNo(),'DEPARTURESv5');

//RowNo() 1->

//IterNo() 1->

//peek 0->

and then group by  and sum(D_TO_SUM_14)

Not applicable
Author

Hi nowaitaka,

Great! I learnt something new from your implementation as well. Thank you for sharing.

Not applicable
Author

Awesome! this really helped me.