How get the distinct value of calls of distinct ID list? - qlikview

I have the following Problem: assume I have the following table loaded in QlikView:
Now I want to calculate the number of distinct ids, "calls over 60 sec" and the number of distinct "calls from other over 60 sec", if "calls over 60 sec" is 0.
Using For count(distinct(if([calls over 60 sec]>0, ID))) I get = 2, which is correct.
Now for count(distinct(if([calls over 60 sec]=0 and [calls from other over 60 sec]>0, ID))) I get 3.
But the answer I am looking for is 1. Because overall months only 1 id is called by other.
Or do I need Set expression? Basically, I what for the chosen month to calculate the distinct number of ids as well as the conditions above.
I am grateful for every answer.

Try,
COUNT ( DISTINCT { < [calls over 60 sec]={"0"} , [calls from other over 60 sec] = { ">0" } > } ID)
And aggr:
// SUM ( // sometimes
Aggr (
COUNT ( DISTINCT { < [calls over 60 sec]={"0"} , [calls from other over 60 sec] = { ">0" } > } ID)
, year, month
)
// )
And, pls, don't use "IF" in formulas

Related

SQL - Calculate percentage by group, for multiple groups

I have a table in GBQ in the following format :
UserId Orders Month
XDT 23 1
XDT 0 4
FKR 3 6
GHR 23 4
... ... ...
It shows the number of orders per user and month.
I want to calculate the percentage of users who have orders, I did it as following :
SELECT
HasOrders,
ROUND(COUNT(*) * 100 / CAST( SUM(COUNT(*)) OVER () AS float64), 2) Parts
FROM (
SELECT
*,
CASE WHEN Orders = 0 THEN 0 ELSE 1 END AS HasOrders
FROM `Table` )
GROUP BY
HasOrders
ORDER BY
Parts
It gives me the following result:
HasOrders Parts
0 35
1 65
I need to calculate the percentage of users who have orders, by month, in a way that every month = 100%
Currently to do this I execute the query once per month, which is not practical :
SELECT
HasOrders,
ROUND(COUNT(*) * 100 / CAST( SUM(COUNT(*)) OVER () AS float64), 2) Parts
FROM (
SELECT
*,
CASE WHEN Orders = 0 THEN 0 ELSE 1 END AS HasOrders
FROM `Table` )
WHERE Month = 1
GROUP BY
HasOrders
ORDER BY
Parts
Is there a way execute a query once and have this result ?
HasOrders Parts Month
0 25 1
1 75 1
0 45 2
1 55 2
... ... ...
SELECT
SIGN(Orders),
ROUND(COUNT(*) * 100.000 / SUM(COUNT(*), 2) OVER (PARTITION BY Month)) AS Parts,
Month
FROM T
GROUP BY Month, SIGN(Orders)
ORDER BY Month, SIGN(Orders)
Demo on Postgres:
https://dbfiddle.uk/?rdbms=postgres_10&fiddle=4cd2d1455673469c2dfc060eccea8020
You've stated that it's important for the total to be 100% so you might consider rounding down in the case of no orders and rounding up in the case of has orders for those scenarios where the percentages falls precisely on an odd multiple of 0.5%. Or perhaps rounding toward even or round smallest down would be better options:
WITH DATA AS (
SELECT SIGN(Orders) AS HasOrders, Month,
COUNT(*) * 10000.000 / SUM(COUNT(*)) OVER (PARTITION BY Month) AS PartsPercent
FROM T
GROUP BY Month, SIGN(Orders)
ORDER BY Month, SIGN(Orders)
)
select HasOrders, Month, PartsPercent,
PartsPercent - TRUNCATE(PartsPercent) AS Fraction,
CASE WHEN HasOrders = 0
THEN FLOOR(PartsPercent) ELSE CEILING(PartsPercent)
END AS PartsRound0Down,
CASE WHEN PartsPercent - TRUNCATE(PartsPercent) = 0.5
AND MOD(TRUNCATE(PartsPercent), 2) = 0
THEN FLOOR(PartsPercent) ELSE ROUND(PartsPercent) -- halfway up
END AS PartsRoundTowardEven,
CASE WHEN PartsPercent - TRUNCATE(PartsPercent) = 0.5 AND PartsPercent < 50
THEN FLOOR(PartsPercent) ELSE ROUND(PartsPercent) -- halfway up
END AS PartsSmallestTowardZero
from DATA
It's usually not advisable to test floating-point values for equality and I don't know how BigQuery's float64 will work with the comparison against 0.5. One half is nevertheless representable in binary. See these in a case where the breakout is 101 vs 99. I don't have immediate access to BigQuery so be aware that Postgres's rounding behavior is different:
https://dbfiddle.uk/?rdbms=postgres_10&fiddle=c8237e272427a0d1114c3d8056a01a09
Consider below approach
select hasOrders, round(100 * parts, 2) as parts, month from (
select month,
countif(orders = 0) / count(*) `0`,
countif(orders > 0) / count(*) `1`,
from your_table
group by month
)
unpivot (parts for hasOrders in (`0`, `1`))
with output like below

Check if the value has been the same for x consecutive days

My goal is to get a list of users(uploaders) which have uploaded 0 byte files for 4 consecutive days.
My current query:
SELECT * FROM file_uploads
JOIN (
SELECT max(date_added) as latest_date
FROM file_uploads
WHERE size = 0
GROUP BY uploader_id
) as list
So in the JOIN I try to get the latest date grouped by uploader where a file is uploaded with the size of 0.
Now I need to check if the size has been 0 for -4 consecutive days since the latest_date, but that is what I can't figure out. Can I check it with a WHERE statement or do I need to do an IF statement or something else.
This is an example of the table I'm working with: https://ibb.co/Sf3RFSk
If there is one row per date, you can filter by the maximum date and then count the number of rows that are 0 for each uploader_id:
select uploader_id
from file_uploads fu
where fu.date_uploaded >= (select max(fu2.date_uploaded) - interval 3 day
from file_uploads fu2
where fu2.uploader_id = fu.uploader_id
) and
fu.size = 0
group by uploader_id
having count(*) = 4;

DAX - Inactive customers

I have a measure like below which returns me all active customers who in the last 90 days bought product category = 'A'
CustomersActive last 90 days:=
VAR Last90Days=
MAX (DimDate[Date) - 90
RETURN
CALCULATE (
DISTINCTCOUNT ( FactSales[CustomerKey]);
DimProduct[Category] = "A";
FILTER (
ALL (DimDate[Date);
DimDate[Date] >= Last90Day
&& DimDate[Date] <= MAX (DimDate[Date])
)
)
Now I need to create a measure INACTIVE CUSTOMERS:
Rule:
Make a list of all distinct customers whose someday bought product = "B" and the date of this was less than my actual filter date
Create a measure using also a distinct count of the last 90 days, but comparing the first list to my actual
If customer was in the first list (product B) and in my last 90 days (product A) is not appearing, then 1, else 0

Dax Measure - Value table compare value

I have a table FactSales
And tried but didn’t get ant satisfactory result.
Id like to calculate old results and compare to my actual one and see how many customers whose bought product B before (before 90 days) didn’t buy the same product in last 3 months according to the date filter
I tried this:
Customers inactive =
VAR Daysbefore90: Max(DimDate[date]) -90
> RETURN CALCULATE( DISTINCTCOUNT(FSales[CustomerKey]); DimProduct[Product] = “A”; FILTER( ALL ( DimDate[Date] );
DimDate[Date] < DaysBefore90 ); NOT(CONTAINS( FILTER(FSales;
RELATED(DimDate[Date]) >= Daysbefore90 && DimDate[Date]) <=
MAX(Daysbefore90): RELATED(DimProduct[Product]) = “A”) ;
FSales[CustomerKey]; FSales[CustomerKey] ) ) )
This will get you all customer who purchased item 'B' in the last 90 Days:
Customers Who Bought Product B 90 Days Ago :=
CALCULATE (
DISTINCTCOUNT ( 'FSale'[CustomerKey] ),
ALL ( 'DimDate'[Date] ),
KEEPFILTERS (
DATESINPERIOD ( 'DimDate'[Date], MAX ( 'DimDate'[Date] ), -90, DAY )
),
KEEPFILTERS ( DimProduct[Product] = "B" )
)
Your question is a little hard to read, so maybe update it and we can go from there.

Calculating progressive pricing in PostgreSQL

I need to calculate revenue based on how many items a user has.
So for example, the first 10 items are free, up to 100 items are 0.50, up to 200 are 0.25 and up to 500 are 0.15 for example.
I have no idea where to start with this, can I get some direction please?
EG. If a user has 365 items, this would be (10 * 0) + (90 * 0.5) + (100 * 0.25) + (165 * 0.15)
Ideally I'd be doing this in python or something, but the dashboarding tool doesn't have that capability...
EDIT:
I should have mentioned that the number of items isn't actually the number they have, it's the limit they have chosen. The limit is saved as a single number in a subscription event. So for each user I will have an integer representing their max items eg. 365
First number items using window function row_number,
then use a case expression to assign a proper value for each item.
Simple example: http://sqlfiddle.com/#!17/32e4a/9
SELECT user_id,
SUM(
CASE
WHEN rn <= 10 THEN 0
WHEN rn <= 100 THEN 0.5
WHEN rn <= 200 THEN 0.25
WHEN rn <= 500 THEN 0.15
ELSE 0.05
END
) As revenue
FROM (
SELECT *,
row_number() OVER (partition by user_id order by item_no ) As rn
FROM mytable
) x
GROUP BY user_id
I should have mentioned that the number of items isn't actually the
number they have, it's the limit they have chosen. The limit is saved
as a single number in a subscription event. So for each user I will
have an integer representing their max items eg. 365
In this case the below query probably fits your needs:
Demo: http://sqlfiddle.com/#!17/e7a6a/2
SELECT *,
(SELECT SUM(
CASE
WHEN rn <= 10 THEN 0
WHEN rn <= 100 THEN 0.5
WHEN rn <= 200 THEN 0.25
WHEN rn <= 500 THEN 0.15
ELSE 0.05
END
)
FROM generate_series(1,t.user_limit) rn
)
FROM mytab t;