Except, Distinct in MDX - distinct

Good morning. I'm workin' on a project where i have to calculate the fidelity client kpi. the formula is : (Number of client of year x1 - Number of new client of year x2)/(Number of client of year x1).
So, i have the fact table which contain the foreign key of the degenerate client dimension (PK_Client), im trying this mdx request but it doesn't work :
`Nonempty(
Distinct(
EXCEPT(
(([Dim Client].[PK Client].[PK Client]),
([Dim Temps 3].[Annee Nom].CurrentMember.PrevMember,
[Measures].[Remise Facture])),
(([Dim Client].[PK Client].[PK Client]),
([Dim Temps 3].[Annee Nom].CurrentMember,
[Measures].[Remise Facture]))
)
)
).Count
)
/
Nonempty(Distinct([Dim Client].[PK Client].[PK Client]),
([Dim Temps 3].[Annee Nom].CurrentMember.PrevMember,
[Measures].[Remise Facture])).Count`
i always get 0. can anyone help me

I found it :
100*(1 -
Except(
Nonempty(
Distinct([Dim Client].[PK Client].[PK Client]),
([Dim Temps 3].[Annee Nom].PrevMember,
[Measures].[Remise Facture])
),
Nonempty(
Distinct([Dim Client].[PK Client].[PK Client]),
([Dim Temps 3].[Annee Nom].CurrentMember,
[Measures].[Remise Facture])
)).Count
/
Nonempty(
Distinct([Dim Client].[PK Client].[PK Client]),
([Dim Temps 3].[Annee Nom].PrevMember,
[Measures].[Remise Facture])
).Count)

Related

Adding a new column with sequential numbers that repeat over and over again

How do we add a column to the results of the query below in order to assign...
Key_Week1 to the 1st record
Key_Week2 to the 2nd record
Key_Week3 to the 3rd record
Key_Week1 to the 4th record
Key_Week2 to the 5th record
Key_Week3 to the 6th record
Key_Week1 to the 7th record
Key_Week2 to the 8th record
Key_Week3 to the 9th record
And on and on and on...following the above pattern repeatedly?
Alternatively, you can use 1, 2 and 3 instead of Key_Week1,
Key_Week2 and Key_Week3 for the new columns values
select distinct trunc(GenerateTimeBy1Day,'day') as claim_eff_date, trunc(GenerateTimeBy1Day,'day') + 20 AS bwe_to_complete_by from
(
select from_dt + (level - 1)/1 as GenerateTimeBy1Day
from (select from_dt
,to_dt
,to_dt - from_dt + 1 as days_between
from (select to_date('22-Dec-2019') as from_dt
, to_date('30-Dec-2040') as to_dt
from dual))
connect by (level - 1) <= days_between
)
order by claim_eff_date
Current Results:
(Simply run the above query. No sample data is needed)
Claim_Eff_Date
BWE_To_Complete_By
22-DEC-19
11-JAN-20
29-DEC-19
18-JAN-20
05-JAN-20
25-JAN-20
12-JAN-20
01-FEB-20
19-JAN-20
08-FEB-20
26-JAN-20
15-FEB-20
02-FEB-20
22-FEB-20
09-FEB-20
29-FEB-20
16-FEB-20
07-MAR-20
Desired Results:
Claim_Eff_Date
BWE_To_Complete_By
Key_Week_Group
22-DEC-19
11-JAN-20
Key_Week1
29-DEC-19
18-JAN-20
Key_Week2
05-JAN-20
25-JAN-20
Key_Week3
12-JAN-20
01-FEB-20
Key_Week1
19-JAN-20
08-FEB-20
Key_Week2
26-JAN-20
15-FEB-20
Key_Week3
02-FEB-20
22-FEB-20
Key_Week1
09-FEB-20
29-FEB-20
Key_Week2
16-FEB-20
07-MAR-20
Key_Week3
OR
Claim_Eff_Date
BWE_To_Complete_By
Key_Week_Group
22-DEC-19
11-JAN-20
1
29-DEC-19
18-JAN-20
2
05-JAN-20
25-JAN-20
3
12-JAN-20
01-FEB-20
1
19-JAN-20
08-FEB-20
2
26-JAN-20
15-FEB-20
3
02-FEB-20
22-FEB-20
1
09-FEB-20
29-FEB-20
2
16-FEB-20
07-MAR-20
3
And on and on and on
One option is just to calculate the row_number() and then do a mod to get the repitition.
with your_data as (
select distinct trunc(GenerateTimeBy1Day,'day') as claim_eff_date,
trunc(GenerateTimeBy1Day,'day') + 20 AS bwe_to_complete_by
from
(
select from_dt + (level - 1)/1 as GenerateTimeBy1Day
from (select from_dt
,to_dt
,to_dt - from_dt + 1 as days_between
from (select to_date('22-Dec-2019') as from_dt
, to_date('30-Dec-2040') as to_dt
from dual))
connect by (level - 1) <= days_between
)
order by claim_eff_date
)
select your_data.*,
mod( row_number() over (order by claim_eff_date) - 1, 3 ) + 1 key_week_group
from your_data

Count of customers whose rating is lowered more than 3 this year

I am here with a DAX/PBI question.
I have a table that contains Customer number, rating date and rating. (which is shown below). Each customer has several rating notes in different dates, as shown below:
CustomerNumber RatingDate Rating
887 01.10.2020 2
887 31.12.2019 5
887 06.01.2020 3
887 31.12.2018 3
940 10.07.2020 14
940 31.12.2019 10
656 01.05.2020 8
656 31.12.2019 8
I want to create a measure and place it on a card that shows the count of customers whose rating dropped more than 3 levels in this year (compare between last rating in 2019 and last rating in 2020).
As in this example table, result should be 1 (cus. number 940)
However the measure that i wrote doesnt seem to be working: (blank result)
COUNTROWS(
FILTER('Rating Change';
IF(COUNTROWS(FILTER('Rating Change';'Rating Change'[Ratingdate].[Year]=2020))=0;BLANK();
IF(COUNTROWS(FILTER('Rating Change';'Rating Change'[Ratingdate].[Year]=2019))=0;BLANK();
CALCULATE(MAX('Rating Change'[Rating]);FILTER('Rating Change';'Rating Change'[Ratingdate].[Year]=2019)) -
CALCULATE(MAX('Rating Change'[Rating]);FILTER('Rating Change';'Rating Change'[Ratingdate].[Year]=2020))>3
)
)
Probably you have an error in your sample data, because 940 has increased his Level;
The solution could look like this:
measure = countrows(FILTER (
ADDCOLUMNS (
VALUES ( 'Rating Change'[CustomerNumber] ),
"maxRating",
CALCULATE (
MAX ( 'Rating CHange'[Rating] ),
FILTER (
ALL ( 'Rating Change'[RatingDate] ),
VAR _x =
CALCULATE (
MAX ( 'Rating Change'[RatingDate] ),
YEAR ( 'Rating Change'[RatingDate] ) = YEAR ( TODAY () )
)
RETURN
'Rating Change'[RatingDate] = _x
)
),
"maxRatingLY",
CALCULATE (
MAX ( 'Rating CHange'[Rating] ),
FILTER (
ALL ( 'Rating Change'[RatingDate] ),
VAR _x =
CALCULATE (
MAX ( 'Rating Change'[RatingDate] ),
YEAR ( 'Rating Change'[RatingDate] )
= YEAR ( TODAY () ) - 1
)
RETURN
'Rating Change'[RatingDate] = _x
)
)
),
[maxRatingLY] - [maxRating] > 3
)
)

How to compare the same columns in different rows?

I have extracted data like below
Name Session CATEGORY HT WT BMI
John SESSION 1 OW 1.5 64.6 28.71
John SESSION 3 OW 1.52 63.2 27.35
Eric SESSION 1 OW 1.48 55.7 25.43
Eric SESSION 3 OW 1.52 55.4 23.98
I would want it in the below format
Name session_1_Category Session_1_height session_1_weight session_1_BMI session_3_Category Session_3_height session_3_weight session_3_BMI
John OW 1.5 64.6 28.71 OW 1.52 63.2 27.35
Eric OW 1.48 55.7 25.43 OW 1.52 55.4 23.98
I'm using oracle database. Please help me with a SQL query to extract data in the above format.
In Oracle, you can use PIVOT:
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE TABLE_NAME ( Name, "Session", CATEGORY, HT, WT, BMI ) AS
SELECT 'John', 'SESSION 1', 'OW', 1.5, 64.6, 28.71 FROM DUAL UNION ALL
SELECT 'John', 'SESSION 3', 'OW', 1.52, 63.2, 27.35 FROM DUAL UNION ALL
SELECT 'Eric', 'SESSION 1', 'OW', 1.48, 55.7, 25.43 FROM DUAL UNION ALL
SELECT 'Eric', 'SESSION 3', 'OW', 1.52, 55.4, 23.98 FROM DUAL;
Query 1:
SELECT *
FROM table_name
PIVOT(
MAX( HT ) AS height,
MAX( WT ) AS weight,
MAX( BMI ) AS BMI
FOR "Session" IN (
'SESSION 1' AS Session_1,
'SESSION 3' AS Session_3
)
)
Results:
| NAME | CATEGORY | SESSION_1_HEIGHT | SESSION_1_WEIGHT | SESSION_1_BMI | SESSION_3_HEIGHT | SESSION_3_WEIGHT | SESSION_3_BMI |
|------|----------|------------------|------------------|---------------|------------------|------------------|---------------|
| John | OW | 1.5 | 64.6 | 28.71 | 1.52 | 63.2 | 27.35 |
| Eric | OW | 1.48 | 55.7 | 25.43 | 1.52 | 55.4 | 23.98 |
Here is another solution without using PIVOT tables and will work across platforms-
SELECT NAME
,MAX(CASE WHEN Session = 'SESSION 1' THEN CATEGORY END) AS session_1_Category
,MAX(CASE WHEN Session = 'SESSION 1' THEN HT END) AS Session_1_height
,MAX(CASE WHEN Session = 'SESSION 1' THEN HT END) AS session_1_weight
,MAX(CASE WHEN Session = 'SESSION 1' THEN HT END) AS session_1_BMI
,MAX(CASE WHEN Session = 'SESSION 3' THEN HT END) AS session_3_Category
,MAX(CASE WHEN Session = 'SESSION 3' THEN HT END) AS Session_3_height
,MAX(CASE WHEN Session = 'SESSION 3' THEN HT END) AS session_3_weight
,MAX(CASE WHEN Session = 'SESSION 3' THEN HT END) AS session_3_BMI
FROM YOUR_TABLE
GROUP BY NAME

Find number of Wednesdays (or other weekday) in a month - Oracle SQL

I found this query for finding the number of Sundays in a month.
I have been tinkering with it but cannot figure out how to change it to get, say, the number of Wednesdays in a month, for example. Can you show me how?
with
months as (
select add_months(trunc(sysdate,'YEAR'),level-13) month
from dual
connect by level <= 36
)
select to_char(month,'YYYY') year,
to_char(month,'Month') month,
to_char(month,'Day') first_day,
to_char(last_day(month),'Day DD') last_day,
4+
case
when to_char(last_day(month),'DD') - decode(to_char(month,'D'),1,0,8 -to_char(month,'D')) >= 29
then 1
else 0
end nb_sunday
from months
Here's the game: You give me a year (like 2015) and a day of the week, in the form of a three-letter string (like 'Wed'). I will return a table with each month of that year and with the count of days-of-week equal to your input in each month.
Simply implementing here the suggestion from my Comment to MT0's Answer. I am hard-coding the year and the day-of-week (in a CTE) since "how to pass parameters to a query" (through bind variables and such) is not the focus in this thread.
with
inputs ( yr, day_of_week ) as (
select 2015, 'Wed' from dual
),
prep ( dec31 ) as (
select to_date(to_char(yr - 1) || '-12-31', 'yyyy-mm-dd') from inputs
)
select to_char(add_months(dec31, level), 'Mon-yyyy') as mth,
( next_day(add_months(dec31, level) , day_of_week) -
next_day(add_months(dec31, level - 1), day_of_week) ) / 7 as cnt
from inputs cross join prep
connect by level <= 12;
MTH CNT
-------- ----
Jan-2015 4
Feb-2015 4
Mar-2015 4
Apr-2015 5
May-2015 4
Jun-2015 4
Jul-2015 5
Aug-2015 4
Sep-2015 5
Oct-2015 4
Nov-2015 4
Dec-2015 5
12 rows selected.
The last wednesday of the month is given by:
TRUNC( NEXT_DAY( LAST_DAY( :month ) - INTERVAL '7' DAY, 'WEDNESDAY' ) )
The first wednesday of the month is given by:
NEXT_DAY( TRUNC( :month, 'MM' ) - INTERVAL '1' DAY, 'WEDNESDAY' )
Subtracting gives the number of days between them. Divide by 7 and add 1 and you get the number of Wednesdays:
SELECT ( TRUNC( NEXT_DAY( LAST_DAY( :month ) - INTERVAL '7' DAY, 'WEDNESDAY' ) )
- NEXT_DAY( TRUNC( :month, 'MM' ) - INTERVAL '1' DAY, 'WEDNESDAY' )
) / 7 + 1
AS number_of_wednesdays
FROM DUAL;
Or you can just use the difference between the first Wednesday of the month and of the next month as suggested by #mathguy
SELECT ( NEXT_DAY(
ADD_MONTHS( TRUNC( :month, 'MM' ), 1 ) - INTERVAL '1' DAY,
'WEDNESDAY'
)
- NEXT_DAY(
TRUNC( :month, 'MM' ) - INTERVAL '1' DAY,
'WEDNESDAY'
)
) / 7
AS number_of_wednesdays
FROM DUAL;

how do we get the multiple rows into single row

with ces as
(select account_num,
imsi,
previous_month,
current_month,
status
from (
select account_num,
imsi,
to_char(u.previous_month,'yyyymmdd')previous_month,
to_char(u.current_month,'yyyymmdd')current_month,
ls.status
from ( select account_num
,imsi
,case when usage_date < add_months(to_date('20151110','yyyymmdd'),-1) then usage_date
else null
end previous_month
,case when usage_date >= add_months(to_date('20151110','yyyymmdd'),-1) then usage_date
else null
end current_month
from genevabatchuser.loadusagedata
where event_source = 'NUMEREXROMHYB'
and account_num = 'ACC000142'
and imsi in ('310640100000003','310640100000004','310640100000338','310640100000331')
)u full outer join GENEVABATCHUSER.TMOLOADIMSILIST ls using (account_num,imsi)
)
)
select * from ces
where imsi in ('310640100000003','310640100000004','310640100000338','310640100000331')
Im seeing the output like below:
ACCOUNT_NUM IMSI PREVIOUS_MONTH CURRENT_MONTH
ACC000142 310640100000003 10/8/2015 5:18:29 AM
ACC000142 310640100000003 11/3/2015 11:25:33 PM
ACC000142 310640100000003 11/3/2015 5:18:29 AM
ACC000142 310640100000003 10/8/2015 11:25:33 PM
My Expected output is:
ACCOUNT_NUM IMSI PREVIOUS_MONTH CURRENT_MONTH
ACC000142 310640100000003 10/8/2015 5:18:29 AM 11/3/2015 11:25:33 PM
It appears that what you want to do is something like
with ces as (select account_num,
imsi,
u.previous_month,
u.current_month
ls.status
from (select account_num,
imsi,
case
when usage_date < add_months(to_date('20151110','yyyymmdd'),-1) then usage_date
else null
end previous_month,
case
when usage_date >= add_months(to_date('20151110','yyyymmdd'),-1) then usage_date
else null
end current_month
from genevabatchuser.loadusagedata
where event_source = 'NUMEREXROMHYB' and
account_num = 'ACC000142' and
imsi in ('310640100000003','310640100000004','310640100000338','310640100000331'))u
full outer join GENEVABATCHUSER.TMOLOADIMSILIST ls
using (account_num, imsi))
select ACCOUNT_NUM,
IMSI,
MIN(PREVIOUS_MONTH) AS PREVIOUS_MONTH,
MAX(CURRENT_MONTH) AS CURRENT_MONTH
from ces
where imsi in ('310640100000003','310640100000004','310640100000338','310640100000331')
GROUP BY ACCOUNT_NUM, IMSI;
Best of luck.

Resources