using subcube in names set in mdx - filter

In AdventureWork2012 I write this Query:
select
[Measures].[Internet Sales Amount] on columns,
[Ship Date].[Calendar Year].[Calendar Year] .members on rows
from
[Adventure Works]
where
[Sales Territory].[Sales Territory Country].&[Australia];
But I want to write this query in a named set in my multidimensional Cube.
I can not use filter function because I can not filter a dimension based on another dimension. I have searched a lot and I found using sub cube like this:
select [Measures].[Internet Sales Amount] on columns,
[Ship Date].[Calendar Year].[Calendar Year] .members on rows
from
(Select [Sales Territory].[Sales Territory Country].&[Australia] on columns from [Adventure Works])
But I want to create a named set in my cube in order to showing the Years on axis just for Australia. But I don't know how can I write sub cube in my Named set. Please help me.

Is this the sort of Set you require?
WITH SET [OzzieYears] AS
NonEmpty(
[Ship Date].[Calendar Year].[Calendar Year].members,
(
[Sales Territory].[Sales Territory Country].&[Australia]
,[Measures].[Internet Sales Amount]
)
)
SELECT {} on 0,
[OzzieYears] on 1
FROM [Adventure Works]
To create within your cube script follow a walkthrough such as this : https://msdn.microsoft.com/en-us/library/ms166594.aspx
The expression within the WITH clause should help. The NonEmpty functionreturns a SET:
NonEmpty(
[Ship Date].[Calendar Year].[Calendar Year].members,
(
[Sales Territory].[Sales Territory Country].&[Australia]
,[Measures].[Internet Sales Amount]
)
)
I don't play around with cube scripts but I'd guess you could add something like this:
CREATE SET CURRENTCUBE.[OzzieYears]
AS NonEmpty(
[Ship Date].[Calendar Year].[Calendar Year].members,
(
[Sales Territory].[Sales Territory Country].&[Australia]
,[Measures].[Internet Sales Amount]
)
), DISPLAY_FOLDER = 'Sets' ;

Related

Revenue Growth in Oracle for Quarter 1 vs Quarter 2

Calculating Revenue Growth in Oracle for Quarter 1 vs Quarter 2 ->
I have a sales table with columns of dt_invoice_date, sale value. I used this self-join query-
select
yr1,qtr2, qtr1, sales1,sales2, (sales1-sales2)/sales2*100 as growth
from (
select
extract(year from dt_invoice_date) yr1,
TRUNC(EXTRACT(MONTH FROM dt_invoice_date) / 3) qtr1,
sum(sale_value) as sales1
from base_sales_data_tbl
group by extract(year from dt_invoice_date),
TRUNC(EXTRACT(MONTH FROM dt_invoice_date) / 3)
) S1
left outer join
(
select
extract(year from dt_invoice_date) yr2,
TRUNC(EXTRACT(MONTH FROM dt_invoice_date) / 3) qtr2,
sum(sale_value) as sales2
from base_sales_data_tbl
group by extract(year from dt_invoice_date),
TRUNC(EXTRACT(MONTH FROM dt_invoice_date) / 3)
) S2 ON (yr1 = yr2 AND qtr2-1 = qtr1)
where qtr1= 1 and qtr2= 2
order by yr1;
Now, this is giving me the answer but it takes time. So, I tried to use the recursive query ->
with s1 as (
select
sum(s.sale_value) sales,
to_char(dt_invoice_date,'yyyyq') yrq,
lag(sum(s.sale_value),1) over (order by to_char(dt_invoice_date,'yyyyq')) sales_pq
from base_sales_data_tbl s
where to_char (dt_invoice_date,'q') <3
group by to_char(dt_invoice_date,'yyyyq')
)
select
yrq,
lag(yrq,1) over (order by yrq) prev_q,
sales, sales_pq, round((sales-sales_pq)*100/sales_pq,2) growth
from s1
order by yrq;
But the result that I am getting is something like this
Here I want to compare the qtr1 vs qtr 2 revenue in same year. This query is giving me the revenue growth for 2015 Qtr 1 vs 2014 Qtr 2 also which I don't require. Kindly help.
You can easily filter data from your result, comparing yearq and prev_q, but there is also pivot which makes all for you:
select yr, q1, q2, q2/q1 - 1 as growth
from (select sale_value, to_char(dt_invoice_date, 'yyyy') yr, to_char(dt_invoice_date, 'q') q
from base_sales_data_tbl
where to_char(dt_invoice_date, 'q') < 3)
pivot (sum(sale_value) for q in (1 q1, 2 q2))
demo
There is a very small mistake.
You need to use partition by clause in lag function.
Something like this:
lag(sum(s.sale_value),1) over (partition by trunc(dt_invoice_date,'YEAR') order by to_char(dt_invoice_date,'yyyyq')) sales_pq
And use the same in group by clause.
group by trunc(dt_invoice_date,'YEAR'),
to_char(dt_invoice_date,'yyyyq'))
Cheers!!

Calculate Bottom Third's Average in DAX

I am attempting to get the average of the lower third of the data that has wages sorted by wages ascending. I have tried to just return the TOPN using a FILTER to not include BLANK() wage values. I then need to just select the column I care about in the AVERAGE calculation. So I wrote something like the following where [withSalaryJobCount] is a calculated measure that is only the count of rows that have a non-BLANK annualSalary column:
entryWages:= AVERAGE(
SELECTCOLUMNS(
CALCULATE(
TOPN(
[withSalaryJobCount]- [withSalaryJobCount]/3,
'table',
'table'[salaryAnnual],
ASC
),
FILTER(table, [salaryAnnual] <> BLANK())
),[entryWages]
"bottomThird",
[salaryAnnual]
)
)
This is failing with an error that:
The AVERAGE function only accepts a column reference as an argument
Original Question:
I have a set of SQL calculations that give me the percentile wages as well as what we term the entry and experience level wages. The list of wages are entered into a table sorted by their value with an IDENTITY column. A much simplified query to insert and calculate the percentile, entry, and experienced wages is listed below:
CREATE TABLE #t1 (
id int identity,
salaryannual decimal(18,2)
)
INSERT INTO #t1
SELECT salaryannual
FROM table a
ORDER BY salaryannual
SELECT
(SELECT AVG(CAST(salaryannual AS BIGINT)) FROM #t1 WHERE ID>=minID AND ID<=minID+(ct/3)) entryLevelSalary,
(SELECT AVG(CAST(salaryannual AS BIGINT)) FROM #t1 WHERE ID>=maxID-(ct/3) AND ID<=maxID) experiencedSalary,
(select AVG(CAST(salaryannual AS BIGINT)) from #t1 where ID = minID + (ct/2+1)/2 or ID = minID + (ct/2+1)/2 + (ct/2+1)%2) q1,
(select AVG(CAST(salaryannual AS BIGINT)) from #t1 where ID = minID + (ct+1)/2 or ID = minID + (ct+1)/2 + (ct+1)%2 ) median,
(select AVG(CAST(salaryannual AS BIGINT)) from #t1 where ID = minID + ct+1 - ((ct/2+1)/2 + (ct/2+1)%2) or ID = minID + ct+1 -((ct/2+1)/2) ) q3,
(SELECT AVG(CAST(salaryannual AS BIGINT)) FROM #t1 WHERE ID>=minID AND ID<=maxID) avgSal
FROM
(
SELECT COUNT(*) ct, MIN(ID) minID, MAX(ID) maxID
FROM #t1
) uniqueIDs
Converting the percentile calculation is of the form:
pct25Wages:= Calculate(PERCENTILE.INC('table'[salaryAnnual], .25), FILTER([withSalaryCount] > 6))
The FILTER is used because we have a minimum requirement that there be at least 7 entries with a salary going forward.
My question is how to convert the entry/experience into a DAX/measure query?
(SELECT AVG(CAST(salaryannual AS BIGINT)) FROM #t1 WHERE ID>=minID AND ID<=minID+(ct/3)) entryLevelSalary,
(SELECT AVG(CAST(salaryannual AS BIGINT)) FROM #t1 WHERE ID>=maxID-(ct/3) AND ID<=maxID) experiencedSalary,
I have tried using a STDDEV and AVG wage calculation like below but it does not give expected results and looking at it I can see it would not work as I expected anyway:
entryWages:= [avgWages] + 3 * [StdDevWage]
So, after much banging my head against a wall this is how I accomplished this.
First I needed to rank my rows in the set by the [salaryAnnual] column. But, since many entries can have the same salary I also tweaked the calculation a bit by using the uniqueID assigned to the row:
RANKX(
'TABLE',
'TABLE'[salaryAnnual] + ('TABLE'[ID] / 1000000000),
,
ASC
)
Then I used this value to give me the bottom third of rows with salary (measure [withSalaryJobCount]):
TOPN(
1 + ( [withSalaryJobCount]/3),
'TABLE',
RANKX(
'TABLE',
'TABLE'[salaryAnnual] + ('TABLE'[ID] / 1000000000),
,
ASC
),
ASC
)
Finally I needed to only get the [salaryAnnual] column that was not null and only pull out the [salaryAnnual] column from the calculated table to do the average of:
AVERAGEX(
SELECTCOLUMNS(
CALCULATETABLE(
TOPN(
1 + ( [withSalaryJobCount]/3),
'TABLE',
RANKX(
'TABLE',
'TABLE'[salaryAnnual] + ('TABLE'[ID] / 1000000000),
,
ASC
),
ASC
),
FILTER(TABLE, [salaryAnnual] <> BLANK())
),
"bottomThird",
'TABLE'[salaryAnnual]
), [bottomThird]
)

Translate window function into DAX

i have a logic within a stored procedure that I'd like to translate into DAX.
Since i am rather new and I am probably searching with the wrong keywords, i cannot figure out how to transform this windowing function into propper dax.
select FIRST_VALUE(v) OVER(PARTITION BY partid ORDER BY somedate DESC, somenumber DESC) as myval
FROM table1
The query takes the first value of a group flagged wit hthe same partid (respecting the descending order of first somedate and then somenumber).
Can you please hint me into the right direction?
The following would give you one value based on the highest somedate and somenumber. If you bring in the someid as a slicer then you should get what you're looking for.
=
CALCULATE (
MAX ( 'Table'[Column] ),
FILTER (
'Table',
[somedate] = CALCULATE ( MAX ( [somedate] ), ALL ( 'Table' ) )
),
FILTER (
'Table',
[somedate] = CALCULATE ( MAX ( [somenumber] ), ALL ( 'Table' ) )
)
)

Oracle Quarter SQL Query with top three products

I am working on a small project in Oracle. I need to get the top three best-selling products and the total amounts taken on these for the year and for each of the four quarters April-June, July-September, October-December and January-March. I have already found the first part, I simply need help getting the 4 quarter totals for each product. Hope someone can help, thank you
This is the SQL commands used so far:
select * from (
select "FACTQUANTITY"."PRODUCTID" as "PRODUCTID",
"DIMPRODUCT"."PRODUCTNAME" as "PRODUCTNAME",
sum(FACTQUANTITY.QUANTITY) as "QUANTITY"
from "FACTQUANTITY" "FACTQUANTITY",
"DIMPRODUCT" "DIMPRODUCT"
where "DIMPRODUCT"."PRODUCTID"="FACTQUANTITY"."PRODUCTID"
group by FACTQUANTITY.PRODUCTID,
DIMPRODUCT.PRODUCTNAME
order by sum(FACTQUANTITY.QUANTITY) desc
)
WHERE ROWNUM <= 3;
You can start from here:
select
trunc(fact_table.date_column,'Q') as quarter,
"FACTQUANTITY"."PRODUCTID" ,
"DIMPRODUCT"."PRODUCTNAME",
sum(FACTQUANTITY.QUANTITY) as "QUANTITY"
from "FACTQUANTITY" JOIN "DIMPRODUCT"
ON "DIMPRODUCT"."PRODUCTID"="FACTQUANTITY"."PRODUCTID"
group by
FACTQUANTITY.PRODUCTID, DIMPRODUCT.PRODUCTNAME, trunc(fact_table.date_column,'Q')
;
Subsequently, you can:
with a as (<previous query>)
select *
from (
select
quarter,
productid,
productname,
quantity,
row_number() over (partition by quarter order by quantity desc) rnk
from a
)
where rnk <= 3;
SELECT *
FROM (
SELECT *,
ROW_NUMBER() OVER ( PARTITION BY quarter
ORDER BY quantity DESC, PRODUCTNAME ASC ) AS rn
FROM (
SELECT TRUNC( f.datetime, 'Q' ) AS quarter,
f.PRODUCTID,
d.PRODUCTNAME,
sum(f.QUANTITY) AS QUANTITY
FROM FACTQUANTITY f
INNER JOIN
DIMPRODUCT d
ON ( d.PRODUCTID = f.PRODUCTID )
GROUP BY TRUNC( f.datetime, 'Q' ),
FACTQUANTITY.PRODUCTID,
DIMPRODUCT.PRODUCTNAME
)
)
WHERE rn <= 3;

Finding top 5 region and within region find top 5 customer by their price. (HIVE)

We have one requirement where we want to find top N region by their price sum and then find top N customers for each of the region.
Sample Data.
REGION_NAME,CUSTOMER_NAME,PRICE
RG1,Customer1,100
RG1,Customer2,200
RG1,Customer3,100
RG2,Customer4,100
RG2,Customer5,200
RG2,Customer6,400
RG3,Customer7,100
RG3,Customer8,200
RG3,Customer9,500
RG3,Customer9,200
Assume we want Top 2 region and Top 2 customer within each region by summing the price
Region_name,Region_sum,Customer_name,Customer_price (Sum)
RG3,1000,Customer9,700 (Sum of customer price)
RG3,1000,Customer8,200
RG2,700,Customer6,400
RG2,700,customer5,200
How to write HIVE query for this? We are not able to think how to write this using HIVE. We may have to write MapReduce or PIG?
You can do this in Hive using analytics functions and a self-join:
select regions_ranked.region_name, regions_ranked.region_sum, customers_ranked.customer_name, customers_ranked.customer_sum from
(
select region_name, customer_name, customer_sum, rank() over (partition by region_name order by customer_sum desc) as customer_rank from (
select region_name, customer_name, sum(price) as customer_sum
from foo group by region_name, customer_name
) customers_sum
) customers_ranked
join
(
select region_name, region_sum, rank() over (order by region_sum desc) as region_rank from (
select region_name, sum(price) as region_sum
from foo group by region_name
) regions_sum
) regions_ranked
on customers_ranked.region_name = regions_ranked.region_name
where region_rank <= 2 and customer_rank <= 2;
This gives the exact output that you were looking for, although out of order. You can tack on an "order by" clause at the very end if you want that.

Resources