merge two mdx queries - mdx

I have two MDX queries.
First query :
SELECT {[Measures].[Actual]} ON 0,
{ DESCENDANTS([Dim Office].[Offices].[Office Level 02].ALLMEMBERS)
*DESCENDANTS([Dim Business Line].[Business Lines].[Business Line Level 02].ALLMEMBERS)
*{[Dim Date].[Fiscal Dim Date Calculations].&[Current Dim Date]}} ON 1
FROM
[BI]
Second one :
SELECT {[Measures].[Actual]} ON 0,
{ DESCENDANTS([Dim Office].[Offices].[Office Level 02].ALLMEMBERS)
*[Dim PNL].[PNL].&[6]
*{[Dim Date].[Fiscal Dim Date Calculations].&[Current Dim Date]}} ON 1
FROM
[BI]
How can I get the union of the two queries ?

try this,
SET1 as
{ DESCENDANTS([Dim Office].[Offices].[Office Level 02].ALLMEMBERS)
*DESCENDANTS([Dim Business Line].[Business Lines].[Business Line Level 02].ALLMEMBERS)
*{[Dim Date].[Fiscal Dim Date Calculations].&[Current Dim Date]}}
SET2 as
{ DESCENDANTS([Dim Office].[Offices].[Office Level 02].ALLMEMBERS)
*[Dim PNL].[PNL].&[6]
*{[Dim Date].[Fiscal Dim Date Calculations].&[Current Dim Date]}}
SET3 as
Union(SET1,SET2)
select {[Measures].[Actual]} ON 0,
SET3 on 1
From [BI]

There is a workaround, you could use T-SQL EXEC statement to make such thing. Please check my answer here, to find the way to query AS server from SQL server. In short, you just need two temp tables:
declare #tsqlquery1 varchar(1000) = ...
declare #mdxquery1 varchar(1000) = ''' SELECT {[Measures].[Actual]} ON 0,
{ DESCENDANTS([Dim Office].[Offices].[Office Level 02].ALLMEMBERS)
*DESCENDANTS([Dim Business Line].[Business Lines].[Business Line Level 02].ALLMEMBERS)
*{[Dim Date].[Fiscal Dim Date Calculations].&[Current Dim Date]}} ON 1
FROM
[BI])'''' + ''' + ')'
-- same for second mdx
...
-- add temp tables
create table #t1 (...)
create table #t2 (...)
-- insert MDX results into temp table1
insert into #t1
EXEC(#tsqlquery1 + #mdxquery1)
-- insert MDX results into temp table2
insert into #t2
EXEC(#tsqlquery2 + #mdxquery2)
-- get union
select * from #t1 union select * from #t2

If you mean you want to concatenate the results of both queries, this is not possible in MDX. MDX is a strongly typed language, and a report has to have the same structure with regard to hierarchy on all axes. And your row axes differ: the first uses [Dim Business Line].[Business Lines] as the second hierarchy, and the second uses [Dim PNL].[PNL] as the second hierarchy.
You should concatenate both results in the client tool that you are using.

Related

SQL Insert Set of Values Optimized

The goal is to create a table with sample data in Teradata for a year. A way to do it, is to copy the first 6 entries of similar data and just alter the timestamp 365 times (for my usecase).
I didn't know better and wrote a procedure
REPLACE PROCEDURE stackoverflow()
BEGIN
DECLARE i INTEGER DEFAULT 0;
DELETE FROM TestTable;
WHILE i < 365 DO
INSERT INTO TestTable
SELECT
TestName
,Name_DT + i
FROM
(SELECT TOP 6
*
FROM TestTable2
WHERE Name_DT = '2021-12-15') AS sampledata;
SET i = i + 1;
END WHILE;
END;
This works, but is awfully slow. Also the IT department doesn't want us to use procedures. Is there a better way to achieve the same result without a procedure?
The generic way to get repeated data is a CROSS JOIN:
SELECT
TestName
,calendar_date
FROM
( SELECT TOP 6 *
FROM TestTable2
WHERE Name_DT = DATE '2015-12-15'
) AS sampledata
CROSS JOIN
( SELECT calendar_date
FROM sys_calendar.CALENDAR
WHERE calendar_date BETWEEN DATE '2011-12-15'
AND DATE '2011-12-15' + 364
) AS cal
;
In your case there's Teradata's proprietary EXPAND ON syntax to create time series:
SELECT TestName, Begin(pd)
FROM
( SELECT TOP 6 *
FROM TestTable2
WHERE Name_DT = DATE '2015-12-15'
) AS sampledata
-- create one row per day in the range
EXPAND ON PERIOD(Name_DT, Name_DT +365) AS pd

Query multiple tables that have date pattern appended to their names

Dears,
We have a database that creates a new table for each new day. The naming of the tables follows this pattern: History_tbl_[year]_[month]_[day]. A sample name of the tables for the last 5 days for example is:
History_tbl_2021_10_02
History_tbl_2021_10_01
History_tbl_2021_09_30
History_tbl_2021_09_29
History_tbl_2021_09_28
My goal is to be able to query all the tables from a given date range at once. I can manually select the tables with union all, but it takes lots of time especially if I want to do a long date range. Is there a better way to solve this?
Note: Unfortunately, I don't have the privilege to change the structure and make all data being stored in a single table.
One bare-bones method to generate a list of unioned queries and dynamically execute them would be as follows, tweak as necessary:
declare #from date='20211001', #to date='20211004', #sql nvarchar(max)='';
with d as (
select DateAdd(day, number, #from) dt
from master..spt_values
where type = 'P'
and DateAdd(day, number, #from) <= #to
)
select #sql=String_Agg(qry,' ')
from (
select 'select col1, col2, col3 from History_tbl_'
+ Concat(Year(dt),'_',Right(Concat('0',month(dt)),2),'_', Right(Concat('0',Day(dt)),2))
+ Iif( dt=Max(dt) over() ,'', ' union all') qry
from d
)x
exec sp_executesql #sql
Note that the CTE generates the date range on the fly, ideally you would use a permanent calendar table

sql - the data equals to the end of the months within the data

i need the data which equals to the end of the months in the same table.
what i was struggling so far is :
SELECT * FROM LG_006_01_EMFLINE H
where h.DATE_ in (
declare #start datetime
declare #end datetime
select #Start = (select MIN(mm.date_) as minimum FROM LG_006_01_EMFLINE mm where mm.accountcode like '335%' and mm.DATE_ > '2016-04-01')
select #End = (select MAX(nn.date_) FROM LG_006_01_EMFLINE nn where nn.accountcode like '335%' and nn.DATE_ > '2016-04-01')
;With CTE as
(
Select #Start as Date,Case When DatePart(mm,#Start)<>DatePart(mm,#Start+1) then 1 else 0 end as [Last]
UNION ALL
Select Date+1,Case When DatePart(mm,Date+1)<>DatePart(mm,Date+2) then 1 else 0 end from CTE
Where Date<#End
)
Select date from CTE
where [Last]=1 OPTION ( MAXRECURSION 0 ) )
the error i get is :
Msg 156, Level 15, State 1, Line 7 Incorrect syntax near the keyword
'declare'. Msg 102, Level 15, State 1, Line 26 Incorrect syntax near
')'.
thanks in advance...
You say that the code within your in statement works fine on its own, but as a_horse_with_no_name correctly pointed out, you can't have declare statements or ctes within a sub select.
Consequently you need to rearrange your query a little. As you have not provided your source schema or data I have not been able to test this:
declare #start datetime
declare #end datetime
select #Start = (select MIN(mm.date_) as minimum
FROM LG_006_01_EMFLINE mm
where mm.accountcode like '335%'
and mm.DATE_ > '20160401' -- Remove the hyphens to ensure SQL knows exactly what your date is, avoiding localisation issues.
)
select #End = (select MAX(nn.date_)
from LG_006_01_EMFLINE nn
where nn.accountcode like '335%'
and nn.DATE_ > '20160401' -- Remove the hyphens to ensure SQL knows exactly what your date is, avoiding localisation issues.
)
;With CTE as
(
Select #Start as Date
,Case When DatePart(mm,#Start) <> DatePart(mm,#Start+1) then 1 else 0 end as [Last]
union all
Select Date+1
,Case When DatePart(mm,Date+1) <> DatePart(mm,Date+2) then 1 else 0 end
from CTE
Where Date < #End
)
select *
from LG_006_01_EMFLINE H
where h.DATE_ in (
Select date
from CTE
where [Last]=1
)
option ( maxrecursion 0 )

Parsing a string in SQL with If statement

I have a table with a string in some columns values that tells me if I should delete the row....however this string needs some parsing to understand whether to delete or not.
What is the string: it tells me the recurrence of meetings eg everyday starting 21st march for 10 meetings.
My table is a single column called recurrence:
Recurrence
-------------------------------
daily;1;21/03/2015;times;10
daily;1;01/02/2016;times;8
monthly;1;01/01/2016;times;2
weekly;1;21/01/2016;times;4
What to do: if the meetings are finished then remove the row.
The string is of the following format
<frequency tag>;<frequency number>;<start date>;times;<no of times>
For example
daily;1;21/03/2016;times;10
everyday starting 21st march, for 10 times
Does anybody know how I would calculate if the string indicates all meetings are in past? I want a select statement that tells me if the recurrence values are in past - true or false
I added one string ('weekly;1;21/05/2016;times;4') that definitely must not be deleted to show some output. At first try to add to temp table `#table1' all data from your table and check if all is deleted well.
DECLARE #table1 TABLE (
Recurrence nvarchar(max)
)
DECLARE #xml xml
INSERT INTO #table1 VALUES
('daily;1;21/03/2016;times;10'),
('daily;1;21/03/2015;times;10'),
('daily;1;01/02/2016;times;8'),
('monthly;1;01/01/2016;times;2'),
('weekly;1;21/01/2016;times;4'),
('weekly;1;21/05/2016;times;4')
SELECT #xml= (
SELECT CAST('<s><r>' + REPLACE(Recurrence,';','</r><r>') + '</r><r>'+ Recurrence+'</r></s>' as xml)
FROM #table1
FOR XML PATH ('')
)
;WITH cte as (
SELECT t.v.value('r[1]','nvarchar(10)') as how,
t.v.value('r[2]','nvarchar(10)') as every,
CONVERT(date,t.v.value('r[3]','nvarchar(10)'),103) as since,
t.v.value('r[4]','nvarchar(10)') as what,
t.v.value('r[5]','int') as howmany,
t.v.value('r[6]','nvarchar(max)') as Recurrence
FROM #xml.nodes('/s') as t(v)
)
DELETE t
FROM #table1 t
LEFT JOIN cte c ON c.Recurrence=t.Recurrence
WHERE
CASE WHEN how = 'daily' THEN DATEADD(day,howmany,since)
WHEN how = 'weekly' THEN DATEADD(week,howmany,since)
WHEN how = 'monthly' THEN DATEADD(month,howmany,since)
ELSE NULL END < GETDATE()
SELECT * FROM #table1
Output:
Recurrence
-----------------------------
weekly;1;21/05/2016;times;4
(1 row(s) affected)

Auto increment values with alpha numeric

I am trying automatically increment the alpha numeric field (say for productid in product table).
But I am getting an error (see below).
Could somebody please look into this error or any other approach to achieve this task?
My table details:
create table tblProduct
(
id varchar(15)
)
create procedure spInsertInProduct
AS
Begin
DECLARE #PId VARCHAR(15)
DECLARE #NId INT
DECLARE #COUNTER INT
SET #PId = 'PRD00'
SET #COUNTER = 0
--This give u max numeric id from the alphanumeric id
SELECT #NId = cast(substring(id, 3, len(id)) as int) FROM tblProduct group by left(id, 2) order by id
--here u increse the vlaue to numeric id by 1
SET #NId = #NId + 1
--GENERATE ACTUAL APHANUMERIC ID HERE
SET #PId = #PId + cast(#NId AS VARCHAR)
INSERT INTO tblProduct(id)values (#PId)
END
I am gettin the following error:
Msg 8120, Level 16, State 1, Procedure spInsertInProduct, Line 10
Column 'tblProduct.id' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Msg 8120, Level 16, State 1, Procedure spInsertInProduct, Line 10
Column 'tblProduct.id' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.**
SELECT #NId = max(
cast(substring(id, 4, len(id)) as int)
)
FROM tblProduct;
This assumes your substring function is returning the numeric portion of your id. I made changes since in other examples your id's start with PRD.
Side note: There is no reason to have you Product ID's start with PRD in the database. If this were an identity field, you could set it to increment by 1 and in any display just have: 'PRD' + Cast(ID as varchar25)) as ProductID. Maybe it is not that simple of all ID's do not start with the same three letters.
Your line
SELECT #NId = cast(substring(id, 3, len(id)) as int)
FROM tblProduct
group by left(id, 2)
order by id
is not doing what you were wanting it to. It is failing because you can't include id in the select directly, because you're grouping by left(id, 2), not id itself. You cannot put something into the select statement when grouping, unless it is part of the Group By, or an aggregate (such as SUM and MAX.)
(Edit: Corrected, Left and Substring are not 0 based--to get the PRD tag and such, we need substring 4, and left 3.)
The correct way of doing this would be:
SELECT #NId = cast(substring(MAX(id), 4, len(MAX(id))) as int)
FROM tblProduct
group by left(id, 3)
order by left(id, 3)
I have tested your stored procedure in SQL Server 2000 and Query Analyzer it works very well. Just I have removed create table code from that.