Mdx: query that uses data of another query - mdx

MSAS OLAP
I have 4 dimensions
Userid
Action
Page
ActionOn
Soome Data
Userid 1
Action show
Page: Home
Date: 2017-01-01
Userid: 1
Action: click-button
Page::
Date:: 2016-12-01
I would like to query olap using to retrieve a funnel. What pages were visited in 2017 year by people who had clicked button in December of 2016.
Is any possible solution to do it? How many users I can store in dimension not affecting to performance?

Let's say you want to see distinct count of users which has an action in previous periods and during the current month:
with
member [Measures].[Leads]
as
SUM(
existing [User].[User].[User].Members,
IIF(
[Measures].[PrevPeriods]
and
[Measures].[ActionCount],
1,
NULL
)
)
member [Measures].[PrevPeriods]
as
SUM(
NULL:[Date].[Calendar].PrevMember,
[Measures].[ActionCount]
)
select
[Measures].[Leads] on 0,
non empty [Page].[Page].[Page].Members on 1
from
[TheCube]
where [Date].[Calendar].[Month].[201701]

Related

Date scaffolding with multiple different date measures?

I want to show the amount of people in each contract status historically. I have a list of every contract's start date, suspension dates, expiration date, and termination state. As a brief example this is what my table looks like:
Client
Location
StartDate
ExpDate
SuspensionStart
SuspensionEnd
TerminatedDate
Jane
NJ
1/1/22
1/1/23
3/1/22
5/1/22
NULL
John
NY
11/15/22
11/15/23
NULL
NULL
3/8/22
Alice
NY
3/12/21
3/12/22
6/1/21
8/1/21
NULL
Jack
NJ
6/20/21
6/20/22
NULL
NULL
NULL
My goal is to get my table to look like this for the month of March
Active
Suspended
Expired
Terminated
1
1
1
1
Then be able to drill down by location too.
Since I have two variables that I want to count by the date (count if expdate=month/year and count of terminateddate=month/year) and then two variables with through dates.
One more piece of context...this data is pulled from a using a sql query from a shared snowflake database. There is no calendar table and I cannot create one except by a view which I used
select
dateadd(day,seq,dt::date) dat
,year(dat) as "YEAR"
,quarter(dat) as "QUARTER OF YEAR"
,month(dat) as "MONTH"
,day(dat) as "DAY"
,dayofmonth(dat) as "DAY OF MONTH",
dayofweek(dat) as "DAY OF WEEK",dayname(dat) as dayName,
dayofyear(dat) as "DAY OF YEAR"
from (
select seq4() as seq, dateadd(month, 1, '2015-01-01'::date) dt
from table(generator(rowcount => 16000))
)
I haven't used scaffolding before, and unsure which date to build the relationship on/join on?
Scaffolding is best done by Tableau Prep. There are multiple steps involved and Prep can step through them while it is very challenging with Tableau Desktop. See https://www.tableau.com/about/blog/2018/12/scaffold-data-tableau-prep-fill-gaps-your-data-set-99389 for one example of how to scaffold the data.
You can apply the techniques in the blog article and create the four metrics that you want to show.

Rolling window new and returning users Bigquery SQL

So I am trying to create a rolling 30 day window of new and returning users using google bigquery sql. Initially I used the following post as inspiration to get the amount of active users for this 30 day rolling window:
Count unique ids in a rolling time frame
Now I would like to segment these users into groups of new and returning users where a new user is defined as user has registered in the last 30 days and a returning user already has an account for longer than 30 days. The problem that I run into is that some users will be considered as both new and returning users in some time frame because on some event dates they were still new users while on other event_dates they became returning users. Let's consider the below example how my initial dataset looks like:
Find below my query:
-- Make an array of unique users per day
WITH unique_users_per_day AS (
-- Total Users
SELECT event_date_dt
, user_type
, STRING_AGG(DISTINCT user_pseudo_id) AS unique_users
FROM `dataset.online_users_per_day`
WHERE users_onboarded_ind = 1
GROUP BY event_date_dt, user_type
),
-- Now concatenate all these arrays for shifting 30 days periods. Arrays do no longer contain unique users
aggregated_daily_users AS (
SELECT event_date_dt
, user_type
, STRING_AGG(unique_users) OVER(PARTITION BY user_type ORDER BY UNIX_DATE(event_date_dt)
RANGE BETWEEN 29 PRECEDING AND CURRENT ROW) as users
FROM unique_users_per_day
),
-- Now get back to the unique users per 30 day sliding period
rolling_30day_window_users AS (
SELECT event_date_dt
, user_type
, (SELECT COUNT(DISTINCT id) FROM UNNEST(SPLIT(users)) AS id) Unique30Days
FROM aggregated_daily_users
)
-- Calculate new_users in the 30 day sliding period by subtracting returning users from total users
SELECT DISTINCT event_date_dt
, user_type
, Unique30Days
FROM rolling_30day_window_users
For my watch date or reporting date 2020-06-02, the user with user_id 'user_1' is categorized as both a new and returning user while effectively it should only be categorized as a returning user. How could I prevent this issue of this user to be double categorized ? Note that I am trying to do this for a 1000+ daily users.

Count of new users by Year SQL Query

We have a subscription based business and a table with the account holders details and the signup date
I want to do a query that gets the count of new signups for each year.
I.E.
Table
USER / SIGNUPDATE
User 1 06/08/2013
User 2 06/08/2013
User 3 06/08/2014
User 4 06/08/2014
User 5 06/08/2014
User 6 06/08/2014
User 7 06/08/2014
User 8 06/08/2015
Returning record set
CountOfNewUsers2013 / CountOfNewUsers2014 / CountOfNewUsers2015
2 / 5 / 1
I can get the count for each year individually but not sure how or if I can group them together in one query.
select year(signupdate), count(*) as newusers
from tablename
group by year(signupdate)
You have to group by year of signupdate column.
I noticed you are trying to display the results in one row horizontally. This is not the way this data is typically displayed. it can be done that way, it's just a lot more work. I am assuming you are using SQL Server because you haven't mentioned which system. Here is how to do it with multiple rows (in two columns):
SELECT year(SIGNUPDATE) as [Year]
, count(USER) as CountOfNewUsers
FROM IDontKnowYourTableNameSorry
GROUP BY year(SIGNUPDATE)
Group by and count are the key features here if you want to look up their documentation.

MDX: group by with LastPeriods group by, Mondrian Schema: levelType hours

I'm new to MDX and Mondrian and have two time related questions:
1.)
The MDX command
SELECT NON EMPTY {[Country].[Country].Members} ON COLUMNS, [Time].[2012].[Q1 2012].[2].[2012-02-08]:[Time].[2012].[Q4 2012].[11].[2012-11-08] ON ROWS FROM [MyCube] WHERE {[Measures].[Sales]}
prints the result grouped by days:
2012-02-08 | 2873 | 9829 | ...
2012-02-09 | ...
But I want to define the date range in days and get the result grouped by months:
2012-02 | 34298| ...
2012-03 | ...
2.)
The Mondrian schema documentation lists the time level types TimeYears, TimeQuarters, TimeMonths and TimeDays. Is it possible to define hours too?
Thanks a lot.
1)
The range function in MDX returns members of the level you're using. In your case :
[Time].[2012].[Q1 2012].[2].[2012-02-08]:[Time].[2012].[Q4 2012].[11].[2012-11-08]
You're using days so that's why you're getting all days. Use month instead of days in your range function. In case you do not want the data before the 8th, an option would be using a subselect to filter :
SELECT
NON EMPTY {[Country].[Country].Members} ON COLUMNS,
[Time].[Your month level].members} ON ROWS
FROM (
SELECT
{[Measures].[Sales]} ON 0,
[Time].[2012].[Q1 2012].[2].[2012-02-08]:[Time].[2012].[Q4 2012].[11].[2012-11-08] ON 1,
FROM [MyCube] )
2) Don't know for Mondrian, but in any case you can create a time dimension based on an 'existing' table

select all records from one table and return null values where they do not have another record in second table

I have looked high and low for this particular query and have not seen it.
We have two tables; Accounts table and then Visit table. I want to return the complete list of account names and fill in the corresponding fields with either null or the correct year etc. this data is used in a matrix report in SSRS.
sample:
Acounts:
AccountName AccountGroup Location
Brown Jug Brown Group Auckland
Top Shop Top Group Wellington
Super Shop Super Group Christchurch
Visit:
AcccountName VisitDate VisitAction
Brown Jug 12/12/2012 complete
Super Shop 1/10/2012 complete
I need to select weekly visits and show those that have had a complete visit and then the accounts that did not have a visit.
e.g.
Year Week AccountName VisitStatus for week 10/12/2012 should show
2012 50 Brown Jug complete
2012 50 Top Group not complete
2012 50 Super Shop not complete
e.g.
Year Week AccountName VisitStatus for week 1/10/2012 should show
2012 2 Brown Jug not complete
2012 2 Top Group not complete
2012 2 Super Shop complete
please correct me if am worng
select to_char(v.visitdate,'YYYY') year,
to_char(v.visitdate,'WW') WEAK,a.accountname,v.visitaction
from accounts a,visit v
where a.accountname=v.ACCCOUNTNAME
and to_char(v.visitdate,'WW')=to_char(sysdate,'WW')
union all
select to_char(sysdate,'YYYY') year,
to_char(sysdate,'WW') WEAK,a.accountname,'In Complete'
from accounts a
where a.accountname not in ( select v.ACCCOUNTNAME
from visit v where to_char(v.visitdate,'WW')=to_char(sysdate,'WW'));
The following answer assumes that
A) You want to see every week within a given range, whether any accounts were visited in that week or not.
B) You want to see all accounts for each week
C) For accounts that were visited in a given week, show their actual VisitAction.
D) For accounts that were NOT visited in a given week, show "not completed" as the VisitAction.
If all those are the case then the following query may do what you need. There is a functioning sqlfiddle example that you can play with here: http://sqlfiddle.com/#!3/4aac0/7
--First, get all the dates in the current year.
--This uses a Recursive CTE to generate a date
--for each week between a start date and an end date
--In SSRS you could create report parameters to replace
--these values.
WITH WeekDates AS
(
SELECT CAST('1/1/2012' AS DateTime) AS WeekDate
UNION ALL
SELECT DATEADD(WEEK,1,WeekDate) AS WeekDate
FROM WeekDates
WHERE DATEADD(WEEK,1,WeekDate) <= CAST('12/31/2012' AS DateTime)
),
--Next, add meta data to the weeks from above.
--Get the WeekYear and WeekNumber for each week.
--Note, you could skip this as a separate query
--and just included these in the next query,
--I've included it this way for clarity
Weeks AS
(
SELECT
WeekDate,
DATEPART(Year,WeekDate) AS WeekYear,
DATEPART(WEEK,WeekDate) AS WeekNumber
FROM WeekDates
),
--Cross join the weeks data from above with the
--Accounts table. This will make sure that we
--get a row for each account for each week.
--Be aware, this will be a large result set
--if there are a lot of weeks & accounts (weeks * account)
AccountWeeks AS
(
SELECT
*
FROM Weeks AS W
CROSS JOIN Accounts AS A
)
--Finally LEFT JOIN the AccountWeek data from above
--to the Visits table. This will ensure that we
--see each account/week, and we'll get nulls for
--the visit data for any accounts that were not visited
--in a given week.
SELECT
A.WeekYear,
A.WeekNumber,
A.AccountName,
A.AccountGroup,
IsNull(V.VisitAction,'not complete') AS VisitAction
FROM AccountWeeks AS A
LEFT JOIN Visits AS V
ON A.AccountName = V.AccountName
AND A.WeekNumber = DATEPART(WEEK,V.VisitDate)
--Set the maxrecursion number to a number
--larger than the number of weeks you will return
OPTION (MAXRECURSION 200);
I hope that helps.