I already posted this problem many times, but unfortunately nobody could understand, I m sorry for my poor english :(
I reformulate ...
I have following fact table
I want to get records that match with a particular date and day of week (JOUR) in all dates range (DATE_DEB, DATE_FIN)
I can do that in SQL like this:
SELECT DATE_DEB,
DATE_FIN,
ID_HOR,
to_char(HR_DEB,'hh24:mi:ss') as HR_DEB,
to_char(HR_FIN,'hh24:mi:ss') as HR_FIN,
JOUR
FROM GRP_HOR HOR, GRP
WHERE GRP.ID_ACTIV_GRP = HOR.ID_ACTIV_GRP
AND TO_DATE('1998-01-08', 'YYYY-MM-DD') between DATE_DEB and DATE_FIN
AND 1 + TRUNC(TO_DATE('1998-01-08', 'YYYY-MM-DD')) - TRUNC(TO_DATE('1998-01-08', 'YYYY-MM-DD'), 'IW') = JOUR
So, I'll get 29 records (see below) which included in each range and match with the day of week (JOUR ), after that I want to enlarge them by hours (HR_DEB, HR_FIN).
The problem is, what's how the best way to do this ?
Create 2 date dimension and link them with DATE_DEB, DATE_FIN.
Create 2 Time dimension and link them with HR_DEB, HR_FIN.
How can I implement the between SQL clause in MDX ? Or geater than or Less than ?
Thank you in advance.
OUTPUT :
To specify a range of dates in MDX you just use the colon operator :
Here is the documentation on MSDN: https://learn.microsoft.com/en-us/sql/mdx/range-mdx?view=sql-server-2017
This is the example they give:
With Member [Measures].[Freight Per Customer] as
(
[Measures].[Internet Freight Cost]
/
[Measures].[Customer Count]
)
SELECT
{[Ship Date].[Calendar].[Month].&[2004]&[1] : [Ship Date].[Calendar].[Month].&[2004]&[3]} ON 0,
[Product].[Category].[Category].Members ON 1
FROM
[Adventure Works]
WHERE
([Measures].[Freight Per Customer])
Related
I have a table of account numbers by date and 24 hourly intervals
ACCT# ; Date ; hour1, hour2, hour3......hour24
there could be as many as 365 days per account# I would like to find the average of all the intervals as well as the as max interval for each acct#. I tried to add sample data but since it is my first post I can't attach it (need+10 posts) –
"customer_number" "date" "est_hb_0000" "est_hb_0100" "est_hb_0200" "est_hb_0300" "est_hb_0400" "est_hb_0500" "est_hb_0600" "est_hb_0700" "est_hb_0800" "est_hb_0900" "est_hb_1000" "est_hb_1100" "est_hb_1200" "est_hb_1300" "est_hb_1400" "est_hb_1500" "est_hb_1600" "est_hb_1700" "est_hb_1800" "est_hb_1900" "est_hb_2000" "est_hb_2100" "est_hb_2200" "est_hb_2300"
Thanks in advance for your help
This SQL should get you close, after you have restructured and populated the table.
Select Customer, Date, HourOfDay, NumAccts
From ActivityStats
Where Customer = 'zzz'
and Date = 'Dt'
and RowNumber < 11
Order By NumAccts Desc
I'm trying to answer questions like, how many POs per month do we have? Or, how many lines are there in every PO by month, etc. The original PO dates are all formatted #1/1/2013#. So my first step was to Format each PO record date into 'mmyy' so I could group and COUNT them.
This worked well but, now I cannot view the data by date... For example, I cannot ask 'How many POs after December did we get?' I think this is because SQL does not recognize mm/yy as a comparable date.
Any ideas how I could restructure this?
There are 2 queries I wrote. This is the query to format the dates. This is also the query I was trying to add the date filter to (ex: >#3/14#)
SELECT qryALL_PO.POLN, Format([PO CREATE DATE],"mm/yy") AS [Date]
FROM qryALL_PO
GROUP BY qryALL_PO.POLN, Format([PO CREATE DATE],"mm/yy");
My group and counting query is:
SELECT qryALL_PO.POLN, Sum(qryALL_PO.[LINE QUANTITY]) AS SUM_QTY_PO
FROM qryALL_PO
GROUP BY qryALL_PO.POLN;
You can still count and group dates, as long as you have a way to determine the part of the date you are looking for.
In Access you can use year and month for example to get the year and month part of the date:
select year(mydate)
, month(mydate)
, count(*)
from tableX
group
by year(mydate)
, month(mydate)
You can format it 'YYYY-MM' , and then use '>' for 'after' clause
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
I have a filter that selects a specific date in my date dimension, This will be passed in as a parameter into the MDX query.
Filter([Date Dimension].[Calendar Year Hierarchy].[Actual Date].members,
[Date Dimension].[Actual Date].CurrentMember.Properties( "Name" ) = '2011-09-01 00:00:00.000')
I would now like to select the weeks and/or months in the hierarchy above that.
[Date Dimension].[Calendar Year Hierarchy].[Month]
[Date Dimension].[Calendar Year Hierarchy].[Calendar Week]
I have tried several functions without much luck such as .Parent and DrillupLevel
I could be using them wrong or in the wrong spot,
thanks for the help
You could use the function GENERATE to get all ascendants:
Generate
(
{Filter([Date Dimension].[Calendar Year Hierarchy].[Actual Date].members,
[Date Dimension].[Actual Date].CurrentMember.Properties( "Name" ) =
'2011-09-01 00:00:00.000')},
{Ascendants([Date Dimension].[Calendar Year Hierarchy].CurrentMember)}
)
Query using Adventure Works:
Select
{[Measures].[Internet Sales Amount]} On Columns,
{Generate(
{Filter([Date].[Calendar].[Date].members,[Date].[Calendar].CurrentMember.Properties("Name") = 'April 1, 2004')},
{Ascendants([Date].[Calendar].CurrentMember)})} On Rows
From [Adventure Works]
If you know the level you're looking for you can use MDX Ancestor function instead of parent:
Ancestor([Date Dimension].[Calendar Year Hierarchy].currentmember,
[Date Dimension].[Calendar Year Hierarchy].[Month])
If no, it's fine using parent function. Note, using properties is not the quickest method to filter (for very large sets).
Why not using to StrToMember MDX function ?
StrToMember( ... here build your member with a string ... )
or if you can edit you mdx directly creating the statement directly with the help of a string builder ?
so the answer i have at the moment is
Filter([Date Dimension].[Calendar Year Hierarchy].[Actual
Date].members, [Date Dimension].[Actual
Date].CurrentMember.Properties( "Name" ) = '2011-09-01 00:00:00.000')
.item(0).parent
using the .item[0] to get the item in the set
and the .parent to get that items parent (in my case i am actually calling it 3 times)
if anyone has any better ideas would love to here them.
You can use STRTOSET and for each input parameter replace ] with ].Parent, this way you will have set of parents.
In my Date Dimension I have 2 hierarchies:
[Year - Week - Date] and [Year - Month - Date]
I want to check in a Cube Calculation if the current level of the Date Dimension is [Date] (the lowest level) or something higher.
How can I achieve this?
Background: I need this to calculate how many working days there were in a period, for an employee.
I currently have this code (untested) that should do the trick for 1 hierarchy, but I guess this will fail when users are using the [Year - Week - Date] hierarchy.
CASE WHEN
[Date].[Year - Month - Date].CURRENTMEMBER.Level
IS
[Date].[Year - Month - Date].[Date]
THEN
//at day level,
//if there is any duration booked, this is a working day
IIF([Measures].[Duration] = 0,0,1)
ELSE
//at higher than day level,
//count days
COUNT(
// where duration > 0 (employee work day)
FILTER(
Descendants([Date].[Year - Month - Date].CURRENTMEMBER, [Date].[Year - Month - Date].[Date]),
[Measures].[Duration] > 0
)
)
END
tl;dr how do I make the above code also work for [Year - Week - Date] hierarchy in the cleanest way possible.
Let's assume the hierarchy (aka attribute) [Date].[Date] exists. If this is the case you can simplify :
COUNT(
FILTER( Existing [Date].[Date].members, [Measures].[Duration] > 0 )
)
The Existing will force to apply an autoexists on the [Date] dimension. This is mainly a performance improvement as it's avoid to evaluate (fact-vise) all tuples.
Once the former examples is clear, we can merge it with your version for the fastest solution (no need for the first iif) :
COUNT(
FILTER( Existing
Descendants([Date].[Year - Month - Date].CURRENTMEMBER, [Date].[Year - Month - Date].[Date],self)
, [Measures].[Duration] > 0 )
)
Further improvements may be possible adding a new measure with a different aggregation type or adding an iif to change which of the two hierarchies is used for descendants (e.g. the one where the currentmember and the defaulmember is not equal)
If you are looking for the cleanest way to calculate how many working days there were in a period, you have to emulate the behavior of regular measure. Otherwise you will get error or bad data in the case of a multiselect on [Date]. In addition, it is desirable to get rid of the Count(Filter(...)) expression to keep the block computation mode (see Optimizing Count(Filter(...)) expressions in MDX). To do this, follow these steps:
Go to the data source view.
Create a new named calculation next to the [Duration] column (in the same fact table).
Column name is "Working days", expression is "null".
Create a new regular measure based on "Working days" column. Aggregation function is Sum.
Write in the MDX script:
(
[Date].[Date].[Date].Members,
[Measures].[Working days]
) = Iif( [Measures].[Duration] > 0, 1, null );
IsLeaf() will tell you if a member is at the bottom level.
Look at SCOPE commands in your calculation script, I do something similar for my YMD calender and my YWD calendar:
CREATE MEMBER CurrentCube.Measures.Example AS NULL //Dummy will be calc'd later
SCOPE (DESCENDANTS([Date].[Calender Y M D],,AFTER));
Measures.Example = 1; //Fill in for monthly calcs
END SCOPE
SCOPE (DESCENDANTS([Date].[Calender Y W D],,AFTER));
Measures.Example = 2; //Fill in for weekly calcs
END SCOPE
The syntax with the ,,AFTER is to exclude the All member if I remember rightly, I'm trying to dif the link up but can't find it. Alternatively, if the calculation works well with the ALL member, just use SCOPE([Date].[Calender Y W D])