MDX DateAdd function over a set of tuples - set

I am trying to create a set of dates using DateAdd() function but I am getting errors while trying to pass a set of tuples as parameter.
The below code returns a member but I am looking for a set of new dates.
WITH
Member [EFF INJ DT] AS
DATEADD("M",12, [INJURY DATE].CurrentMember)
SELECT {[EFF INJ DT]} ON COLUMNS, [INJURY DATE].[DATE].Members ON ROWS
FROM [WVWC DATA CUBE FROI SROI]
I have the following attempt:
WITH
Set [EFF INJ DT] AS
DATEADD("M",12, [INJURY DATE].CurrentMember)
SELECT {[EFF INJ DT]} ON COLUMNS, [INJURY DATE].[DATE].Members ON ROWS
FROM [WVWC DATA CUBE FROI SROI]

Using Adv Works if you want to move 12 members forward then you can navigate in several ways.
Try the following. It should return the date 12 days ahead of the currentmember:
WITH
MEMBER [MEASURES].[EFF INJ DT] AS
[Date].[Calendar].CurrentMember.LEAD(12).MEMBERVALUE
SELECT
{[MEASURES].[EFF INJ DT]} ON 0,
{[Date].[Calendar].[Month].&[2006]&[4].CHILDREN} ON 1
FROM [Adventure Works];
Looks like you want to return the date which is 12 months in the future.
So first we need the year that corresponds to the currentmember via the ANCESTOR function > then go forward to the equivalent date using the COUSIN function like the following:
WITH
MEMBER [MEASURES].[EFF INJ DT] AS
COUSIN(
[Date].[Calendar].CurrentMember,
ANCESTOR(
[Date].[Calendar].CurrentMember,
[Date].[Calendar].[Calendar Year]).LEAD(1)
).membervalue
SELECT
{[MEASURES].[EFF INJ DT]} ON 0,
{[Date].[Calendar].[Month].&[2006]&[4].CHILDREN} ON 1
FROM [Adventure Works];
Adapting to your scenario and assuming that INJURY DATE is a multi-level user hierarchy' that contains another level calledCalendar Year` you could do the following:
WITH
MEMBER [MEASURES].[EFF INJ DT] AS
COUSIN(
[INJURY DATE].CurrentMember,
ANCESTOR(
[INJURY DATE].CurrentMember,
[INJURY DATE].[Calendar Year]).LEAD(1)
).MEMBERVALUE
SELECT
{[MEASURES].[EFF INJ DT]} ON 0,
{[INJURY DATE].[DATE].Members} ON 1
FROM [Adventure Works];
EDIT
Via the VBA tools we have the following in Adv Wrks:
WITH
MEMBER [MEASURES].[EFF INJ DT] AS
DATEADD(
"M",
12,
[Date].[Calendar].CurrentMember.membervalue
)
SELECT
{[MEASURES].[EFF INJ DT]} ON 0,
{[Date].[Calendar].[Month].&[2006]&[4].CHILDREN} ON 1
FROM [Adventure Works];
Adapted to your scenario:
WITH
MEMBER [MEASURES].[EFF INJ DT] AS
DATEADD(
"M",
12,
[INJURY DATE].CurrentMember.membervalue
)
SELECT
{[MEASURES].[EFF INJ DT]} ON 0,
{[INJURY DATE].[DATE].Members} ON 1
FROM [Adventure Works];

Related

Enumerate and add in a column of the select - Oracle

I need to enumerate my lines in a column of the select by a type. For example, I have three types which can be "RR", "RJ" and "RA", every time that a type "RR" appears I have to sum 3 and the other ones I have to sum only 1, creating a sequence like:
Type Number
RR 3
RR 6
RJ 7
RR 10
RJ 11
RA 12
RR 15
I have other fields in the select, so I used the ROW_NUMBER() function with all my order by fields, something like:
select
number,
[...]
type,
ROW_NUMBER() OVER (order by number, type [...] )*3 as sequence
from
my_table
order by number, type [...]
I also tried to use a case statement, but it doesn't aggregate the values.
Is it possible to do? I'm trying to use the ROW_NUMBER() function, but i can't get the result, only three by three.
You could use SUM:
select
number,
[...]
type,
SUM(CASE WHEN Type = 'RR' THEN 3 ELSE 1 END)
OVER (order by number, type [...] ) as sequence
from my_table
order by number, type [...]
Rextester Demo

Max value from Member Property

I need to get the max value of a member property to use in another MDX expression.
As an example from Adventure Works I'm using the following
WITH
MEMBER DoFP AS
[Customer].[Customer].Properties("Date of First Purchase")
MEMBER MaxDoFP AS
Tail
(
NonEmpty
(
[Date].[Date].[Date]
,[Measures].[DoFP]
)
,1
).Item(0).MemberValue
SELECT
[Date].[Calendar Year].[Calendar Year] ON 0
,{
[Customer].[Customer].&[20075]
,[Customer].[Customer].&[15568]
,[Customer].[Customer].&[20285]
} ON 1
FROM [Adventure works]
WHERE
[Measures].[DoFP];
I'd like it to return June 15, 2008 for all rows/cols which is the date of first purchase for Aaron Alexander (who has the max DoFP of the customers selected) so that I can do some more calcs. Instead its giving me 31st Dec 2010 because (I assume) that's the last date in my [Date].[Date].[Date].
Not pretty:
WITH
SET X AS
{
[Customer].[Customer].&[20075]
,[Customer].[Customer].&[15568]
,[Customer].[Customer].&[20285]
}
MEMBER DoFP AS
[Customer].[Customer].Properties("Date of First Purchase")
MEMBER MaxDoFP1 AS
Max(DoFP)
MEMBER MaxDoFP2 AS
Max
(
X
,Cdate([Customer].[Customer].Properties("Date of First Purchase"))
)
SELECT
[Date].[Calendar Year].[Calendar Year] ON 0
,
X * {[Measures].[MaxDoFP1],[Measures].[MaxDoFP2]} ON 1
FROM [Adventure works];
Another option (assuming you have the ability to extend the cube structure) would be to create a measure group based on the customer dimension using a MAX aggregation function. I imagine performance would be a bit better for larger sets.
WITH
SET X AS
{
[Customer].[Customer].&[20075]
,[Customer].[Customer].&[15568]
,[Customer].[Customer].&[20285]
}
MEMBER MaxDoFP AS
Max (X,[Measures].[Customer DoFP MAX])
SELECT
[Date].[Calendar Year].[Calendar Year] ON 0
,X * {[Measures].[MaxDoFP]} ON 1
FROM [Adventure works];

Count rows in own type such as type as table or type as object

My own type
CREATE OR REPLACE TYPE chain_t AS TABLE OF NUMBER(11);
select column as this type in select statement
select
x.id,
cast(multiset(select parent_id from table(x.parents)) as chain_t) as chain
from
xxxx x
if x.parents have values i have next result, for example:
chain_t(22, 44)
or if dont have
chain_t(null)
How i can count rows in chain??
For example in first result 2 rows in second result 0 rows
Use the CARDINALITY() function. Find out more.
select id, chain, cardinality(chain)
from (
select
x.id,
cast(multiset(select parent_id from x) as chain_t) as chain
from x
)
/
Here is a SQL Fiddle based on this simplified version of your posted code.

Multi-column update from SAME table, different rows, in Oracle, with not-null column: Receiving error 01407

I'm getting an error I do not understand.
I have an Oracle database (11g, I think) with a table that has a multi-column unique identifier. It's a transaction table, taking a before and after snapshot of the data from a different table. So far so good, that's all working fine.
We had a bug in our code and I'm trying to fix the data now that the bug is fixed. The bug resulted in the 'after' snapshot having two columns zeroed out in a circumstance where they should have kept their 'before'. So I'm going to update the 'after' snapshot (identified by a transaction type number) to have the same values in those two columns.
I've found all sorts of great help on the multi-column update thing, and I think I have it, except...it generates an error that it cannot update a not-null column to null, when there is no way I can see a null getting in there. Obviously, I am doing something wrong; I just can't tell what.
In some cases, one column can be null - there's an object type column that defines whether that record can have a null value.
The table has this data in it, say:
object_name object_type trans_type trans_date quantity actual_cost
no-quantity 1 1 04/16/2014 {null} 20.00
no-quantity 1 9 04/16/2014 {null} 0.00
needs quantity 2 1 04/16/2014 3 15.00
needs quantity 2 9 04/16/2014 0 0.00
So I need to update the second row (no-quantity, trans_type 9) to actual_cost of 20; quantity can stay null. And I need the 4th row to be updated to quantity of 3, actual_cost of 15.
Here is the query I'm trying to run that is failing - create and insert statements are below:
update demo_table new
set (quantity, actual_cost) =
(
SELECT quantity, actual_cost
FROM demo_table old
WHERE old.object_name = new.object_name
and old.object_type = new.object_type
and old.trans_date = new.trans_date
and old.trans_type = 1
and new.trans_type = 9
)
When I run this I get:
ORA-01407: cannot update ("myschema"."DEMO_TABLE"."ACTUAL_COST") to NULL
(I've tried the other way - update (select col1, col2, etc) - and the table's not set up right for it. Too bad, because that way looked easier to understand...)
Do I maybe need to have an outer where too? The other posts didn't indicate that I did, and I don't know how I would formulate it anyway.
I even get the not-null error on this attempt:
update demo_table new
set (actual_cost) =
(
SELECT actual_cost
FROM demo_table old
WHERE old.object_name = new.object_name
and old.object_type = new.object_type
and old.trans_date = new.trans_date
and old.trans_type = 1
and new.trans_type = 9
and old.object_type = 2
)
object_type of 2 doesn't have a null quantity, and anyway I'm not trying quantity in this one...
The select statement I run to check the actual where clause is correct looks like this:
SELECT old.object_name as old_name, old.object_type as old_type, old.trans_type as old_trans, old.trans_date as old_date,
new.object_name as new_name, new.object_type as new_type, new.trans_type as new_trans, new.trans_date as new_date,
old.quantity as old_quantity, old.actual_cost as old_cost, new.quantity as new_quantity, new.actual_cost as new_cost
FROM demo_table old, demo_table new
WHERE old.object_name = new.object_name
and old.object_type = new.object_type
and old.trans_date = new.trans_date
and old.trans_type = 1
and new.trans_type = 9
That gets the right values, the right old/new fields, only 2 rows returned, as I expect.
Here are my create-and-insert statements:
create table demo_table (
object_name varchar2(30) not null,
object_type number(3) not null,
trans_type number(3) not null,
trans_date timestamp(6) not null,
quantity number(3),
actual_cost number(17,2) not null
)
insert into demo_table (object_name, object_type, trans_type, trans_date, quantity, actual_cost)
values (
'no-quantity', 1, 1, '16-APR-14', null, 20
)
insert into demo_table (object_name, object_type, trans_type, trans_date, quantity, actual_cost)
values (
'no-quantity', 1, 9, '16-APR-14', null, 0
)
insert into demo_table (object_name, object_type, trans_type, trans_date, quantity, actual_cost)
values (
'needs quantity', 2, 1, '16-APR-14', 3, 15
)
insert into demo_table (object_name, object_type, trans_type, trans_date, quantity, actual_cost)
values (
'needs quantity', 2, 9, '16-APR-14', 0, 0
)
I hope my problem is clear. I did look around a lot, but I couldn't find anything that looked like it matched quite closely enough. The same-table thing is not really covered, and the not-nullable column is not really covered. (Or rather, it is, but I couldn't see how the problems described affected my situation.)
I know the table setup is, shall we say, far from ideal. Can't fix it, tonight.
First - +1 on the question - very well written, lots of supporting information, and please accept a huge THANK YOU for providing enough information to solve the problem, including table def and statements to populate the table.
The only real issue with the first update was that the line in the WHERE clause which subsets the NEW table should be pulled out of the subquery and put into the WHERE clause of the UPDATE statement, as in:
update demo_table new
set (new.quantity, new.actual_cost) =
(
SELECT old.quantity, old.actual_cost
FROM demo_table old
WHERE old.object_name = new.object_name
and old.object_type = new.object_type
and old.trans_date = new.trans_date
and old.trans_type = 1
)
where new.trans_type = 9;
I had to fool with this one for quite a while to figure out what was going on. Interesting problem.
SQLFiddle here.
Share and enjoy.

modifying query resultset to include all dates in a range

I have a query which I run on a table TXN_DEC(id, resourceid, usersid, date, eventdesc) which return distinct count of users for a given date-range and resourceid, group by date and eventdesc (each resource can have 4 to 5 eventdesc)
if there is no value of distinct users count on a date in the range, for an eventdesc, then it skips that date row in the resultset.
I need to have all date rows in my resultset or collection such that if there is no value of count for a date,eventdesc combination, then its value is set to 0 but that date still exists in the collection..
How do I go about getting such a collection
I know getting the final dataset entirely from the query result would be too complicated,
but I can use collections in groovy to modify and populate my map/list to get the data in the required format
something similar to following: if
input date range = 5th Feb to 3 March 2011
DataMap = [dateval: '02/05/2011' eventdesc: 'Read' dist_ucnt: 23,
dateval: '02/06/2011' eventdesc: 'Read' dist_ucnt: 23,
dateval: '02/07/2011' eventdesc: 'Read' dist_ucnt: 0, -> this row was not present in query resultset, but row exists in the map with value 0
....and so on till 3 march 2011 and then whole range repeated for each eventdesc
]
If you want all dates (including those with no entries in your TXN_DEC table) for a given range, you could use Oracle to generate your date range and then use an outer join to your existing query. Then you would just need to fill in null values. Something like:
select
d.dateInRange as dateval,
'Read' as eventdesc,
nvl(td.dist_ucnt, 0) as dist_ucnt
from (
select
to_date('02-FEB-2011','dd-mon-yyyy') + rownum - 1 as dateInRange
from all_objects
where rownum <= to_date('03-MAR-2011','dd-mon-yyyy') - to_date('02-FEB-2011','dd-mon-yyyy') + 1
) d
left join (
select
date,
count(distinct usersid) as dist_ucnt
from
txn_dec
where eventDesc = 'Read'
group by date
) td on td.date = d.dateInRange
That's my purely Oracle solution since I'm not a Groovy guy (well, actually, I am a pretty groovy guy...)
EDIT: Here's the same version wrapped in a stored procedure. It should be easy to call if you know the API....
create or replace procedure getDateRange (
p_begin_date IN DATE,
p_end_date IN DATE,
p_event IN txn_dec.eventDesc%TYPE,
p_recordset OUT SYS_REFCURSOR)
AS
BEGIN
OPEN p_recordset FOR
select
d.dateInRange as dateval,
p_event as eventdesc,
nvl(td.dist_ucnt, 0) as dist_ucnt
from (
select
p_begin_date + rownum - 1 as dateInRange
from all_objects
where rownum <= p_end_date - p_begin_date + 1
) d
left join (
select
date,
count(distinct usersid) as dist_ucnt
from
txn_dec
where eventDesc = p_event
group by date
) td on td.date = d.dateInRange;
END getDateRange;

Resources