How to pass apply ssrs parameters on multiple dimension attributes - reporting-services

#StartDate and #EndDate parameters must added to the MDX query for usage in SSRS data set. strtomember can be used like this:
SELECT (
strtomember(#StartDate) : strtomember(#EndDate)
) ON COLUMNS FROM [Cube]
How can I specify that sub-select must work on the [Fact A] and [Fact B] rundate? strtomember(#StartDate) does not specify on which attribute this sub select is going to work. Any pointers?
FROM
(
SELECT
(
[Fact B].[Rundate].&[2015-01-02T00:00:00] : [Fact B].[Rundate].&[2015-01-15T00:00:00]
) ON COLUMNS FROM
(
SELECT
( [Fact A].[Rundate].&[2015-01-02T00:00:00] : [Fact B].[Rundate].&[2015-01-15T00:00:00] ) ON COLUMNS FROM [Cube]
)
)

I know nothing about your requeriments but assuming Fact A and Fact B have different Rundate members I think you should create a #StartDate and #EndDate for every Fact you want to filter.
Also you can have an additional parameter to select the Fact Table, once the Fact Table is selected you can populate date parameters.
If you don't have a Time Dimension related to Fact tables you have to populate parameters from Facts.

Related

SSRS: How can i use a Parameter in MDX Query?

I have been trying for some time to get a Parameter to work within an MDX Query which is automatically generated by SSRS Query Designer.
I have tries the following:
FROM ( SELECT ( {[Dim Date].[Fiscal Year].&[+"#Current_FYear"+]}) ON COLUMNS
FROM ( SELECT ( { [Dim Date].[Fiscal Year].[+"#Current_FYear"+} ) ON COLUMNS
FROM ( SELECT ( {StrToMember(#Current_FYear,CONSTRAINED).lag(23):StrToMember(#Current_FYear, CONSTRAINED)}) ON COLUMNS
FROM ( SELECT ( {[Dim Date].[Fiscal Year].[+"Parameters!Current_FYear.Value"+]}) ON COLUMNS
And none of the above give me the result i am looking for: To have the Dataset filter by the value in the Parameter.
Any help on this would b emuch appreciated!
Thanks,
First of all, I would suggest using the Parameter checkbox in the Query Designer and let SSRS build the MDX for you. Here's a screenshot in case you missed it.
Another reason to let the report create the parameter for you is that it will automatically create another hidden Dataset to populate the available values of the parameter.
If you do want to edit the MDX manually, the syntax could look like this:
SELECT NON EMPTY { [Measures].[Measure] } ON COLUMNS FROM (
SELECT ( STRTOSET(#Parameter, CONSTRAINED) ) ON COLUMNS FROM [Model])
The STRTOSET function converts the parameter value into MDX syntax. It can also handle multi-value parameters.
The parameter you reference here would also need to be defined in the Parameters tab of the Dataset Properties. This is where you link the parameter value from the report to the query.

Parameter as a result

I am looking for a way to use a parameter as a result that can be plugged in to another select statement later down the line.
This is the CTE select statement that I am able to pull by manually changing all four of the dates listed to what I want
SELECT CurrentYearEmp.PRCo,
CurrentYearEmp.Employee,
CASE
WHEN CurrentYearEmp.PREndDate <> '2016-11-20'
THEN '2016-11-20 00:00:00'
WHEN CurrentYearEmp.PREndDate = '2016-11-20'
THEN '2016-11-20 00:00:00'
END AS 'ParameterPREndDate'
I am able to replace the first half of the WHEN statement with a parameter like this
SELECT CurrentYearEmp.PRCo,
CurrentYearEmp.Employee,
CASE
WHEN CurrentYearEmp.PREndDate <> #PREndDate
THEN '2016-11-20 00:00:00'
WHEN CurrentYearEmp.PREndDate = #PREndDate
THEN '2016-11-20 00:00:00'
END AS 'ParameterPREndDate'
But it will only produce the results I am looking for if the parameter is 2016-11-20. I want to be able to have #PREndDate as '2017-02-14' it will post 2017-02-14 as a result of the select statement.
You can use a Table Valued Function as HABO has already said. Here is a simple example for one:
/*
--Create some dummy data in a db
CREATE TABLE SomeData
(
DataId INT IDENTITY
, Val VARCHAR(8)
, Dt DATE
)
INSERT INTO dbo.SomeData (Val, Dt) VALUES ('A', '2017-1-1'),('B', '2017-1-2'),('C', '2017-1-3'),('D', '2017-1-4'),('E', '2017-1-5')
--Create a table valued function
CREATE FUNCTION ReturnData (#StartDt DATE, #EndDt Date)
RETURNS TABLE
AS
Return
Select *
From SomeData
WHERE DT between #StartDt and #EndDt
*/
Select *
From ReturnData('1-1-2017', '1-3-2017')
The best thing IMHO about Table Functions is they can join to existing things as they are well formed objects in the database. When you do Procedures and Dynamic SQL, you get a result set but that does not mean your code can be joined. Table Functions can be cross applied to run off of cte's and they can be joined to other tables. So essentially they are better for reuse but they have rules around them so you cannot do more advanced things like dynamic sql in them(as far as I know unless they changed it recently) and other things. But if you want a reusable data set with rules governing input, that is pretty much exactly what they are made for.

SSAS (MDX) - Filtering Dataset based on another Dataset

I have a mdx report on a cube. As available values for division number report parameter I have an autogenerated dataset (dataset1, with all divisions in company) which query looks like this:
WITH MEMBER [Measures].[ParameterCaption] AS
[Dim Division].[Hierarchy].CURRENTMEMBER.MEMBER_CAPTION
MEMBER [Measures].[ParameterValue] AS
[Dim Division].[Hierarchy].CURRENTMEMBER.UNIQUENAME
MEMBER [Measures].[ParameterLevel] AS
[Dim Division].[Hierarchy].CURRENTMEMBER.LEVEL.ORDINAL
SELECT {[Measures].[ParameterCaption], [Measures].[ParameterValue], [Measures].[ParameterLevel]}
ON COLUMNS ,
[Dim Division].[Hierarchy].ALLMEMBERS
ON ROWS
FROM ( SELECT ( STRTOMEMBER(#FromDimDateHierarchy, CONSTRAINED) : STRTOMEMBER(#ToDimDateHierarchy, CONSTRAINED) )
ON COLUMNS
FROM [ArveCubeBiceps]
)
I have another dataset (dataset2), which consists of only those division numbers, which logged in user is supposed to be able to view (data supplied by a procedure). I need to filter dataset1 available values by the values of dataset2.
-I can't just use the dataset2 as available values for division number, since report query is MDX, and expects tuples, which dataset2 doesn't provide. When I try to concatenate dataset2 values into tuples, I get an error that I can`t use "&" for Object() type.
-When I create a hidden parameter on report, which available and default values are those from dataset2, and then apply a filter expression to dataset1 query, which says "DivisionID in #hidden_parameter" - I get no available values for the Division parameter ( I checked the tables, all data is there )
What do I have to do to get this filter expression working... please help anyone :)
#mmarie
second dataset is created by stored procedure:
USE [Biceps]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[ArveDivisionsByUserID]
#ldapuid nvarchar(30)
AS
BEGIN
declare #hier as hierarchyid
declare #managerID as int
select #managerID = em.employeeID from Dim_Employee2 em where em.ldapuid = #ldapuid
select #hier = dv.hier from Dim_Division dv where dv.managerID = #managerID and hier is not null order by hier desc
select divisionID from Dim_Division dv where hier.IsDescendantOf(#hier)=1 order by hier
END
#FrankPI - offtopic
don't know why, but I used ctrl+k for code, but it`s still regular text :(
If you can change the second query, then this could return the list of allowed members as a set definition string instead of a list of members, using e. g. the SetToStr function. This could then be used in the first query as a parameter replacing the text [Dim Division].[Hierarchy].ALLMEMBERS for the rows by StrToSet(#AllowedDivisionSet, CONSTRAINED).
If the result sets are not huge, the easy way is to do this is with a filter on the Dataset and NOT in MDX:
Add a Boolean filter in which the Expression is =True and the Value is something like this:
=iif(instr(join(Parameters!DataSet2Parameter.Value,","),
Fields!ToDimDateHierarchy.Value)=0,True, False)

MySql sum of custom column

I have a query in which I create custom column names.
At the end of that same table I want a row that will sum all the entries of these custom columns.
For example I have:
SELECT ... IFNULL(bl.amount, '---') AS BudgetAmount,
IFNULL((bl.amount *1) - ( + bal1.amount ), '---') AS Difference
FROM...
I want a column with the sum of BudgetAmount and DIfference columns.
How do I do that?
I think you can use this:
SELECT ... IFNULL(bl.amount, '---') AS BudgetAmount,
IFNULL((bl.amount *1) - ( + bal1.amount ), '---') AS Difference,
IFNULL(bl.amount, 0) + IFNULL((bl.amount *1) - ( + bal1.amount ), 0) AS NewCol
FROM...
Or you could explain more
One easy way to do that is to use your original query as an inline view and write a SELECT statement using the inline view as a rowsource. (In MySQL parlance, the inline view is called a derived table):
SELECT v.BudgetAmount
, v.Difference
, v.BudgetAmount + v.Difference AS Total
FROM (
-- original query here
SELECT ... IFNULL(bl.amount, '---') AS BudgetAmount,
IFNULL((bl.amount *1) - ( + bal1.amount ), '---') AS Difference
FROM...
) v
Unlike other relational database systems, MySQL will actually force the inline view to be materialized (i.e. the query in the inline view is executed and the results are stored as a MyISAM table), and that has performance implications.
But it is a way that you can reference the column aliases for use in other expressions.
(The aliases assigned to the columns can't be referenced in SELECT list where they are assigned... they can only be referenced in the HAVING and ORDER BY clauses of the query.)
To get the values for those columns added into another column in a single query, you can't reference the aliases, you have to to repeat the expressions, like this:
SELECT expr1 AS BudgetAmount
, expr2 AS Difference
, expr1 + expr2 AS Total
FROM ...
To reference the aliases, they need to come from a row source referenced by the query, such as an inline view:
SELECT v.BudgetAmount
, v.Difference
, v.foo
, v.BudgetAmount + v.Difference AS Total
FROM ( SELECT expr1 AS BudgetAmount
, expr2 AS Difference
, foo
FROM ...
) v
I'm not sure that's the answer you wanted to hear, but that's the way it is.
EDIT:
I misunderstood what you were asking. Your question said: "I want a column with the sum of ...". I took that to mean you wanted a query that returned the same number of rows, not that you wanted an additional ROW appended to the result set.
This sounds like a good candidate for app-side summarizing. However, if you really want to do it in MySQL only, there are essentially three options I think.
Write a stored procedure.
Do it in a UNION as others have suggested, which requires putting basically the same subquery twice in one statement.
Try the GROUP BY ... WITH ROLLUP syntax. I'm assuming you have a unique key included in the SELECT, e.g., someUniqueID. You need to group on that ID (so there will be only one row in each group) then use the rollup clause to append the additional row. The ID column will be NULL in the rollup row.
The statement will look something like this, depending on your full query and table structure:
SELECT someUniqueID, ... , IFNULL(SUM(bl.amount), '---') AS BudgetAmount,
IFNULL( SUM( (bl.amount *1) - ( + bal1.amount ) ), '---') AS Difference
FROM ...
GROUP BY someUniqueID
WITH ROLLUP
Sounds like you should do this on the application side. But you can just use UNION ALL at the end to stack the "sum of all entries." Just make sure your columns are aligned.
SELECT amount, balance
FROM table
UNION ALL
SELECT IFNULL(SUM(amount), '---') AS BudgetAmount,
IFNULL(SUM(...)) AS Difference
FROM table

Linq-to-SQL expression to get the max numeric value from a text column

I have an nvarchar SQL column which contains mostly numeric values. I'm trying to come up with an L2S expression that gets me the maximum numeric value while ignoring any non-numeric values.
The SQL that does the job is:
select top 1 value from identifier where and patindex('%[^0-9]%', value) = 0 order by CAST(value AS INT) desc
What LINQ expression can I use to achieve the same thing?
You can do SQL Like queries using the SqlMethods in System.Data.Linq.SqlClient.
(from a in identifier
where !SqlMethods.Like(a.value, "%[^0-9]%")
select a).Max(x => Convert.ToInt64(x.value))
This Linq statement becomes this query according to LinqPad:
-- Region Parameters
DECLARE #p0 VarChar(8) = '%[^0-9]%'
-- EndRegion
SELECT MAX([t1].[value]) AS [value]
FROM (
SELECT CONVERT(BigInt,[t0].[value]) AS [value], [t0].[value]
FROM [Identifier] AS [t0]
) AS [t1]
WHERE NOT ([t1].[value] LIKE #p0)
LinqPad is a great way to play around with queries to see if you can get what you're looking for. I've found that just about the only SQL statements that don't have a good L2S equivalent are ones with the PIVOT keyword. Other than that, there's usually a way to get what you want.
If you want the whole record and not just the MAX() value, you could do the query this way:
(from a in Accounts
orderby (!SqlMethods.Like(a.AccountNumber, "%[^0-9]%") ?
Convert.ToInt64(a.AccountNumber) : 0)
descending
select a).Take(1)