Qlik -create calculated Dimension to show barchart from month start untill filter date(5-4-4 calendar) - date

I have a master calendar(5-4-4) that look like the below image.
I have a Date column in the Sales table. I'm using that Date column in the Selection pane(Filter).
Example Scenario:
now I selected Selection pane date '15-10-2020', bar-chart only showing '15-10-2020' sales only. but I need to look up the master calendar and show the dimension from the start_month date to until selected date
Expected Output: bar chart needs to show dimensions from
'28-09-2020' to '15-10-2020'

The approach is to generate dates from Start_Month to TransDate (made up field name)
Lets say that this is the data we have:
Transactions:
Load * inline [
TransDate , Value
15-10-2020, 100
27-07-2021, 50
];
MasterCalendar_Temp:
Load * inline [
Start_Month, End_Month , Month_number
28-09-2020 , 01-11-2020, 1
02-11-2020 , 29-11-2020, 2
30-11-2020 , 27-12-2020, 3
28-12-2020 , 31-01-2021, 4
01-02-2021 , 28-02-2021, 5
01-03-2021 , 28-03-2021, 6
29-03-2021 , 02-05-2021, 7
03-05-2021 , 30-05-2021, 8
31-05-2021 , 27-06-2021, 9
28-06-2021 , 01-08-2021, 10
02-08-2021 , 29-08-2021, 11
30-08-2021 , 26-09-2021, 12
];
The first step is to find in which interval each TransDate is part of. For this we'll use IntervalMatch function
Inner Join
IntervalMatch ( TransDate )
Load
Start_Month,
End_Month
Resident
MasterCalendar_Temp
;
At this point MasterCalendar_Temp table will look like:
So we now know the perid for each TransDate
The next step is to load the MasterCalendar_Temp data into a separate table but concatenate Start_Month and TransDate into one:
NoConcatenate
MasterCalendar:
Load
Start_Month,
End_Month,
Start_Month & '_' & TransDate as Start_TransDate_Temp
Resident MasterCalendar_Temp;
// we dont need this table anymore
Drop Table MasterCalendar_Temp;
Once we have it we can start creating our dates
// loop through each value in Start_TransDate_Temp field
// for each step extract Start_Month and TransDate values
// use these two values to generate the dates between them
for i = 1 to FieldValueCount('Start_TransDate_Temp')
let value = FieldValue('Start_TransDate_Temp', $(i));
let startDate = num(SubField('$(value)', '_', 1));
let transDate = num(SubField('$(value)', '_', 2));
Dates:
LOAD
date('$(transDate)', 'DD-MM-YYYY') as TransDate,
date($(startDate) + IterNo() - 1, 'DD-MM-YYYY') AS DisplayDates
AUTOGENERATE (1)
WHILE
$(startDate) + IterNo() -1 <= $(transDate)
;
next
// we dont need this table anymore
Drop Table MasterCalendar;
And thats it!
After the script is reloaded we'll have two tables:
Transactions table is untouched and Dates table will have values like this:
As you can see for each TransDate we have the range of dates (from the correcponding Start_Month to TransDate
If we construct a simple bar chart (with DisplayDates as dimension and sum(Value) as measure) and do not apply any selections:
And if select one TransDate:

Related

How to create an inline table from an existing table

I have a table in qlik Sense loaded from the database.
Example:
ID
FRUIT
VEG
COUNT
1
Apple
5
2
Figs
10
3
Carrots
20
4
Oranges
12
5
Corn
10
From this I need to make a filter that will display all the Fruit/Veg records along with records from other joined tables, when selected.
The filter needs to be something like this :
|FRUIT_XXX|
|VEG_XXX |
Any help will be appreciated.
I do not know how to do it in qlicksense, but in SQL it's like this:
SELECT
ID
CASE WHEN FRUIT IS NULL THEN VEG ELSE FRUIT END as FruitOrVeg,
COUNT
FROM tablename
Not sure if its possible to be dynamic. Usually I solve these by creating a new field that combines the values from both fields into one field
RawData:
Load * Inline [
ID , FRUIT ,VEG , COUNT
1 , Apple , , 5
2 , Figs , , 10
3 , ,Carrots , 20
4 , Oranges , , 12
5 , ,Corn , 10
];
Combined:
Load
ID,
'FRUIT_' & FRUIT as Combined
Resident
RawData
Where
FRUIT <> ''
;
Concatenate
Load
ID,
'VEG_' & VEG as Combined
Resident
RawData
Where
VEG <> ''
;
This will create new table (Combined) which will be linked to the main table by ID field:
The new Combined field will have the values like this:
And the UI:
P.S. If further processing is needed you can join the Combined table to the RawData table. This way the Combined field will become part of the RawData table. To achieve this just extend the script a bit:
join (RawData)
Load * Resident Combined;
Drop Table Combined;

Show first and last value in table

I have an excel file with customer's purchasing details (sorted by date).
for example:
customer_id
date
$_Total_purchase
A
1/2/23
5
A
1/3/23
20
A
1/4/23
10
i want to show in table, one row for each customer, so the final table will be:
customer_id
date
purchase_counter
amount_of_last_purchase
amount_of_first_purchase
A
1/4/23
3
10
5
in my table, customer_id is a dimension.
for extracting the date, i use max(date) as measure
for purchase_counter i use count(customer_id)
for extracting 'amount_of_first_purchase', i use firstSortedValue('$_Total_purchase', date)
how can i extract 'amount_of_last_purchase'? is there maybe an aggregation function i can use?
Thanks in advance :)
The simple answer is that you can use -date in you expression and this will return the last record:
FirstSortedValue('$_Total_purchase', -date)
The above will work for the provided data example. When there are more than one customer then Aggr function can help:
First: FirstSortedValue(aggr(sum($_Total_purchase), customer_id, date), date)
Last: FirstSortedValue(aggr(sum($_Total_purchase), customer_id, date), -date)
Another approach (if applied to your case/data) is to flag the first and last records during the data load and use the flags in the measures.
An example script:
RawData:
Load * Inline [
customer_id, date, $_Total_purchase
A, 2/1/23, 5
A, 3/1/23, 20
A, 4/1/23, 10
B, 5/1/23, 35
B, 6/1/23, 40
B, 7/1/23, 50
];
Temp0:
Load
customer_id,
date,
// flag the first record
// if the current row is the beggining of the table then flag as isFirst = 1
// if the customer_id for the current row is different from the previously loaded >-
// customer_id then flag as isFirst = 1
if(RowNo() = 1 or customer_id <> peek(customer_id), 1, null()) as isFirst,
// getting the last is a bit more tricky
// similar logic - if the currrent and previous customer_id are different >-
// or it is the end of the table then get the current customer_id and date >-
// and combine their values. Values are separeted with | ELSE write 0.
// for example: A|4/1/23 or B|7/1/23
if(customer_id <> peek(customer_id) and RowNo() <> 1, peek(customer_id) & '|' & peek(date),
if(RowNo() = NoOfRows('RawData'), customer_id & '|' & date, 0
)) as isLastTemp
Resident
RawData
;
// Get all the data from Temp0 for which isLastTemp is not equal to 0
// split isLastTemp by | -> fist value is customer_id and second is date
// join the result back to the otiginal table
join (RawData)
Load
SubField(isLastTemp, '|', 1) as customer_id,
SubField(isLastTemp, '|', 2) as date,
1 as isLast
Resident
Temp0
Where
isLastTemp <> 0
;
// join Temp0 to the original table
// but only grab the isFirst flag
join(RawData)
Load
customer_id,
date,
isFirst
Resident
Temp0
;
// this table is no longer needed
Drop Table Temp0;
Once the above script is reloaded RawData table will have two more columns - isFirst and isLast:
Then the expressions are simpler:
First: sum( {< isFirst = {1} >} $_Total_purchase)
Last: sum( {< isLast = {1} >} $_Total_purchase)
import pandas as pd
# read excel file
df = pd.read_excel('customer_purchases.xlsx')
# get first value
first_value = df.head(1)
# get last value
last_value = df.tail(1)
you can do with pandas also

How to query a reference table for a value between a dates for a specified category in Apps Script?

I have a background in data analytics and have done a similar workflow in SQL but am brand new to Apps Script. I am a bit at a loss on where to even start in Apps Script. Any advice or pointing me in the direction of useful examples would be truly appreciated!
Currently, I have a reference table on one sheet with categories and values and the start and end date that value applies to. Then I have a data table on another sheet where I add an entry date and a category and I would like to have Apps Script write the corresponding value for that category on the date.
Reference table data (a blank end date means that is the current rate):
Category
Value
Start date
End date
A
25
01/01/2022
3/31/2022
B
40
01/01/2022
C
30
01/01/2022
A
15
04/01/2022
The data table where the entry date and the category are added manually over time. I want to use the reference table to write the value for that category for that entry date.
Entry Date
Category
Value
02/20/2022
B
40
02/27/2022
A
25
03/20/2022
A
25
04/16/2022
C
15
05/12/2022
A
30
06/02/2022
B
40
How do you get the query the reference data for that entry date and category to find the row with the corresponding value?
Description
As I said I'm not good at QUERY but I finally got something to work. I'm sure other can improve on it.
First I created a named range TestQuery for the table of data. I could have just as easily used range "A1:D6"
Next I fill in the End Date with =TODAY() so it has a date value. Then I build my query.
=QUERY(TestQuery,"select B where ( ( A = '"&B11&"' ) and ( date '"&TEXT(A11,"yyyy-mm-dd")&"' > C ) and ( date '"&TEXT(A11,"yyyy-mm-dd")&"' < D ) )")
Reference
Query Language
Compare Dates in Query
Getting data from a table on a sheet
function getData() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName("Sheet0");
const values = sh.getRange("A2:D" + sh.getLastRow()).getValues();
Logger.log(JSON.stringify(values));//2d array
}
A2 is assumed to be the upper left corner of the data

firebird: computing with date

I have SELECT statement from 3 tables. Need help in one WHERE condition. E.g. in first table date field sets date as 2014-02-26, in the second - random integer 7, 14 or 30. So i have something like this SELECT ... JOIN ... WHERE (first_table.date + second_table.integer - NOW) = 1. SELECT and JOIN part I know. I need some help with date computing.
Try this one:
SELECT ...
FROM ...
JOIN ...
WHERE (DATEDIFF(DAY FROM first_table.date TO NOW) + second_table.integer) = 1

Adding Columns heading to report if no data in a given period

I have a dataset for each record it has a CompanyID, RevenueMonth, RevenueYear, Revenue
When I create the report, I am grouping each CompanyID and showing their monthly revenue for a given year.
But in a given year, not all companies have any revenues for a particular month.
Example:
A sample record would look like:
CompanyID, RevenueMonth, RevenueYear, Revenue
1,05,2013,5.00
1,08,2013,6.00
1,03,2013,3.00
End Result, I would like my report to look like this with CompanyID 1.
Company ID|01|02|03|04|05|06|07|08|09|10|11|12
1 0.00|0.00|3.00|0.00|5.00|0.00|0.00|6.00|0.00|0.00|0.00|0.00
In my current Report, it will only fill column headings with March (03), May (05) and August (08).
Company ID|03|05|08
1 3.00|5.00|6.00
How do I get my Report to add the missing months for the year?
I hope my questions is clear.
Database level
Since you're only returning a year at a time, you can create a calendar table and add this to your result set:
Keeping it as simple as possible, with the date table coming from a CTE:
with months as -- get required year/months
(
select RevenueYear = 2013
, RevenueMonth = 1
union all
select RevenueYear = 2013
, RevenueMonth = RevenueMonth + 1
from months
where RevenueMonth < 12
)
select CompanyID = coalesce(r.CompanyID, c.companyID)
, RevenueMonth = coalesce(r.RevenueMonth, m.RevenueMonth)
, RevenueYear = coalesce(r.RevenueYear, m.RevenueYear)
, Revenue = isnull(r.Revenue, 0.0)
from months m
cross join (select distinct CompanyID from records) c -- make sure all companies included
left join records r on m.RevenueYear = r.RevenueYear
and m.RevenueMonth = r.RevenueMonth
SQL Fiddle with demo.
This will return a year/month for each company in the result set.
In the long run it would be better to move from a CTE to a permanent calendar table in the database.
You can then implement this in the report using a matrix style tablix.
Report level
If you'd prefer to do this at the report level, you can set up a table-style tablix with 12 permanent columns, one for each month, then populate the month revenue cells with expressions like:
=Sum(IIf(Fields!RevenueMonth.Value = 2, Fields!Revenue.Value, Nothing)
For the February column.
This would work with your existing dataset without any database code changes.