IIF in With Member comparing dates - ssas

I am very new to MDX and have a basic question. I would like a calculated measure which returns one value for dates less than a specified date, and another value if greater than a specified date. I have attempted:
with member [measures].[tempmeasure] as
IIF
(
[Date].[Date].CurrentMember < [Date].[Date].&[20100501]
, 1
, 2
)
select
[Date].[Date].Members
*
[measures].[tempmeasure] on columns
from [MyCube]
And this does not seem to work. That is using MS SSAS 2008.
Any ideas what I could be doing wrong?

With:
IIF([Date].[Date].CurrentMember < [Date].[Date].&[20100501], 1, 2)
you're comparing two tuple values and not the date members themselves.
You can have a look here for a tutorial on tuples, sets, etc...
As you're using AS, I think you can use the DataDiff function to compute the number of days between your two dates:
DateDiff("d", [Date].[Date].CurrentMember.MemberValue, [Date].[Date].&[20100501].MemberValue )
Otherwise, you may have some member properties available for that purpose:
IIF([Date].[Date].CurrentMember.Properties( 'prop-name', TYPED ) < [Date].[Date].&[20100501].Properties( 'prop-name', TYPED ) , 1, 2)
Cheers.

Please use below expression
IIF
(
[Date].[Date].Currentmember.MemberValue <
[Date].[Date].&[20100501].MemberValue
, 1
, 2
)
I have tested it is working as expected.....
Please let me know if you have any questions

IIF expects a logical expression which returns a boolean value. I think in your case
[Date].[Date].CurrentMember will return a dimension value, a set. Less than operator in this case will cause a syntax error.

Related

Is there a way to divide two halves of a boolean value in sql?

I'm currently working on a task where I'm dealing with a table in which every row has a boolean value, "is_important". I am trying to create a ratio of important entries to total entries grouped by date but I can't seem to get SQL to recognize that I want to divide using a WHERE clause.
One method is:
select date, avg( case when is_important then 1.0 else 0 end) as important_ratio
from t
group by date;
There may also be shortcuts, depending on the database you are using, such as:
avg( is_important )
avg( is_important::int )

Trying to UNNEST timestamp array field, but need to GROUP BY

I have a repeated field of type TIMESTAMP in a BigQuery table. I am attempting to UNNEST this field. However, I must group or aggregate the field in order. I am not knowledgable with SQL, so I could use some help. The code snippet is part of a larger query that works when substituting subscription.future_renewal_dates with GENERATE_TIMESTAMP_ARRAY
subscription.future_renewal_dates is ARRAY<TIMESTAMP>
The TIMESTAMP array is unique (recurring subscriptions) and cannot be generated using GENERATE_TIMESTAMP_ARRAY, so I have to generate the dates before uploading to BigQuery. UDF is too much.
SELECT
subscription.amount AS subscription_amount,
subscription.status AS subscription_status,
"1" AS analytic_name,
ARRAY (
SELECT
AS STRUCT FORMAT_TIMESTAMP("%x", days) AS type_value, subscription.amount AS analytic_name
FROM
UNNEST(subscription.future_renewal_dates) as days
WHERE
(
days >= TIMESTAMP("2019-06-05T19:30:02+00:00")
AND days <= TIMESTAMP("2019-08-01T03:59:59+00:00")
)
) AS forecast
FROM
`mydataset.subscription` AS subscription
GROUP BY
subscription_amount,
subscription_status,
analytic_name
Cannot figure out how to successfully unnest subscription.future_renewal_dates without error 'UNNEST expression references subscription.future_renewal_dates which is neither grouped nor aggregated'
When you do GROUP BY - all expressions, columns in the SELECT (except those in GROUP BY list) should be used with some aggregation function - which you clearly do not have. So you need to decide what it is that you actually trying to achieve here with that grouping
Below is the option I think you had in mind - though it can be different - but at least you have an idea on how to fix it
SELECT
subscription.amount AS subscription_amount,
subscription.status AS subscription_status,
"1" AS analytic_name,
ARRAY_CONCAT_AGG( ARRAY (
SELECT
AS STRUCT FORMAT_TIMESTAMP("%x", days) AS type_value, subscription.amount AS analytic_name
FROM
UNNEST(subscription.future_renewal_dates) as days
WHERE
(
days >= TIMESTAMP("2019-06-05T19:30:02+00:00")
AND days <= TIMESTAMP("2019-08-01T03:59:59+00:00")
)
)) AS forecast
FROM
`mydataset.subscription` AS subscription
GROUP BY
subscription_amount,
subscription_status,
analytic_name

SUM of database function returns much higher value than actual SUM

I have a database function that I am able to get the correct results from, but when I try to use SUM to total the results it returns a much higher value.
SELECT
SUM([DATABASE].[dbo].[fn_GetCharges]([TABLE1_DATE],[TABLE1_CUST],[TABLE1_SITE],[TABLE1_SERV])) AS [GROSS_REVENUE]
FROM [DATABASE].[dbo].[TABLE1]
WHERE
[TABLE1_ROUT] = '1234'
AND [TABLE1_DATE] = '2018-05-08'
This returns a SUM value of about 15,740.
If I remove the SUM and GROUP BY the function then it shows each of the returned values, which I manually totalled to about 750.
I'm using Microsoft SQL Server 2014.
We don't know what is in your function, but you could probably output your raw data first and then sum it next.
;WITH cte AS (
SELECT
[DATABASE].[dbo].[fn_GetCharges]([TABLE1_DATE],[TABLE1_CUST],[TABLE1_SITE],[TABLE1_SERV]) AS [GROSS_REVENUE]
FROM [DATABASE].[dbo].[TABLE1]
WHERE
[TABLE1_ROUT] = '1234'
AND [TABLE1_DATE] = '2018-05-08'
GROUP BY whatever_you_grouped_by_that_gave_correct_results
)
SELECT SUM(gross_revenue) AS gross_revenue
FROM cte
Wondering if you used group by clause in the query since I don't see one posted.
Group By (columns) Having (condition). What you specified in the 'where' goes in the 'Having' clause

Powerpivot-Flag first occurence depending on what user filters

In power pivot, I am trying to figure out how to tag the first occurrence of a visit, based upon what a user filters. For example, if they are looking at calendar year 2014 below is the data. Distinctcount works if you don't care about the time period in which the first count occurs.
If a user filters to March 2014 only, the would see
the following:
this seems tricky at first, but can be done very easily with DAX:
=
IF (
CALCULATE (
MIN ( Visits[VisitID] ),
ALL ( Visits[VisitID] ),
ALL ( Visits[AdmitDate] )
)
- MAX ( [VisitID] )
= 0,
1,
0
)
What this does is very straightforward - it removes the filter on both VisitID and AdmitDate, and by doing so it calculates the minimum for every single Patient ID. Then it subtracts MAX of VisitID for a given row. If the difference equals to 0 (that means this is the first visit), then the value is set to 1, otherwise the value is set to 0.
I have named this measure Check and if you then add it to your table, the result should look like this:
Works well with filtering too (in this case Filter is set on Month = 3):
Alternative approach using RANKX in case of multiple columns
Also, RANKX could be used to achieve this - it seems to be a bit more flexible solution, however I am not sure what would be the performance in a very large dataset.
=
IF (
HASONEVALUE ( Visits[PatientID] ),
IF (
RANKX (
FILTER (
ALLSELECTED ( Visits ),
Visits[PatientID] = MAX ( Visits[PatientID] )
),
[MIN Visit],
,
1,
DENSE
)
= 1,
1,
0
),
DISTINCTCOUNT ( Visits[PatientID] )
)
This works perfectly even if you filter any column. It's a bit complex to understand, but play around a bit with it and also check the linked documentation. What the formula basically does is dynamic RANK across group that is determined by [PatiendID].
The Visit ID is the key item being ranked - you have to use a new measure which I named MIN Visit:
=MIN([VisitID])
The very first IF checks, if the current row is a Total Row, and if so it performs a different calculation to get the total of patients with first visits (by counting distinct values of Patiend ID).
I have updated the source Excel file as well. Here is the link (2013 version).
Hope this helps.
It depends on what you want to ultimately see.
If you just want the first visit date, you would add a calculated field such as:
CALCULATE( FIRSTDATE( 'Date'[Date]), FILTER( Fact, Fact[AdmitDate] >= MIN( 'Date'[Date] ) ) )
IF you want to count the number of patients by date where it was their first visit, based on how the data is sliced, that gets much more complicated.

Calculating Percentage when Row can contain 0

I have previously asked the following question: Calculating percentage within the SQL
Now i was lucky enough to get a great answer however in my question i did not take into account that my rows could contain zero.
The questions row where simple:
select
Number_of_Calls,
Number_of_Answered,
((Number_of_answered/Number_Of_Calls)*100) as answer_percent,
Date
from table Where Date BETWEEN '2012-09-10' AND '2012-09-11'
However Number_of_answered could be zero (if our company did not answer the calls) so if i want the full number in percentage how do i take 0 into account?
By the way. The database that we use is an Oracle database with PL SQL
The nullif function can be used to return null if the divisor is zero. When SQL encounters a null divisor it forces the entire equation to return null, preventing your error from occurring.
select
Number_of_Calls,
Number_of_Answered,
((Number_of_answered/nullif(Number_Of_Calls,0))*100) as answer_percent,
Date
from table Where Date BETWEEN '2012-09-10' AND '2012-09-11'
If you would like to exclude null percentages use the following SQL:
select * from(select
Number_of_Calls,
Number_of_Answered,
((Number_of_answered/nullif(Number_Of_Calls,0))*100) as answer_percent,
Date
from table Where Date BETWEEN '2012-09-10' AND '2012-09-11') alias
where answer_percent is not null;
Case when Number_Of_Calls = 0
THEN 0 --or your desired value, maybe 100
else (Number_of_answered/Number_Of_Calls)*100
END as answer_percent
i think you mean "Number_Of_Calls" could be zero (thus raising a zero_divide error?) if so do
case Number_Of_Calls when 0 then 0 else ((Number_of_answered/Number_Of_Calls)*100) as answer_percent
As far as I understood you from your comment you want a rate of answered calls over a period of time, including days when 100% calls were unanswered.
I guess the simpliest approach would be
select sum(number_of_answered) / sum (number_of_calls)
from table
where date between interval_start and interval_end
in this case.