patternsqlModerate
Dynamically Define a Range in a Dimension
Viewed 0 times
rangedynamicallydefinedimension
Problem
I have an issue that I face every time I decide to build a cube, and I haven't found a way to overcome it yet.
The issue is how to allow the user to define a range of things automatically without having the need to hardcode them in the dimension. I will explain my problem in an example.
I have a table called Customers:
this is the data in the table:
I want to display the data in a pivot style and group up the Salary and Age in defined ranges like below:
I wrote this script and defined the ranges:
My ranges are hard coded and defined. When I copy the data to Excel and view it in a pivot table, it appears like below:
My problem is I want to create a cube by converting the Customers table into a fact table and create 2 dimension tables SalaryDim & AgeDim.
The SalaryDim table has 2 columns (SalaryKey,SalaryRange) and the AgeDim table is similar (ageKey,AgeRange). My Customer fact table has:
I still have to define my ranges inside these dimensions. Every time I connect an Excel pivot to my cube, I can only see these hardcoded defined ranges.
My question is how to define ranges dynamically from the pivot table directly, without creating the range dimensions like AgeDim and SalaryDim. I don't want to only be stuck to the ranges defined in the dimension.
The range defined is '0-25' , '26-30' , '31- 50'. I might want to change it to '0-20', '21-31' , '32-42' and so on, and users request different ranges every time.
Every time I change it, I have to change the dimension. How can I improve this process?
It would be great to have a solution implemented in the
The issue is how to allow the user to define a range of things automatically without having the need to hardcode them in the dimension. I will explain my problem in an example.
I have a table called Customers:
this is the data in the table:
I want to display the data in a pivot style and group up the Salary and Age in defined ranges like below:
I wrote this script and defined the ranges:
SELECT [CustId]
,[CustName]
,[Age]
,[Salary]
,[SalaryRange] = case
when cast(salary as float) 2000 then
'2001+'
end,
[AgeRange] = case
when cast(age as float) = 40 then
'40+'
end
FROM [Customers]
GOMy ranges are hard coded and defined. When I copy the data to Excel and view it in a pivot table, it appears like below:
My problem is I want to create a cube by converting the Customers table into a fact table and create 2 dimension tables SalaryDim & AgeDim.
The SalaryDim table has 2 columns (SalaryKey,SalaryRange) and the AgeDim table is similar (ageKey,AgeRange). My Customer fact table has:
Customer
[CustId]
[CustName]
[AgeKey] --> foreign Key to AgeDim
[Salarykey] --> foreign Key to SalaryDimI still have to define my ranges inside these dimensions. Every time I connect an Excel pivot to my cube, I can only see these hardcoded defined ranges.
My question is how to define ranges dynamically from the pivot table directly, without creating the range dimensions like AgeDim and SalaryDim. I don't want to only be stuck to the ranges defined in the dimension.
The range defined is '0-25' , '26-30' , '31- 50'. I might want to change it to '0-20', '21-31' , '32-42' and so on, and users request different ranges every time.
Every time I change it, I have to change the dimension. How can I improve this process?
It would be great to have a solution implemented in the
Solution
HOW TO DO THIS WITH T-SQL:
As requested this is an alternative to my previous answer that showed how to do it per-user with Excel. This answer shows how to do the same thing shared/centrally using T-SQL instead. I do not know how to do Cubes, MDX or the SSAS stuff for this, so maybe Benoit or someone who does know that can post its equivalent...
Create a new table called "SalaryRangeData" with the following command:
Add calculated columns by wrapping it in a View with this command:
Right-click on the table in SSMS and select "Edit Top 200 Rows". Then enter the following values into the MinVal cells: 0, 501, 1001, and 2001 (order doesn't matter for SQL Server, it will create it for us). Close the table-row editor and do a
Do the exact same steps as in #1 above, except replace all occurrences of "Salary" with "Age". This should make the table "AgeRangeData" and the view "AgeRanges".
Enter the following values into the AgeRangeData [MinVal] column: 0, 15, 20, 30, and 40.
Replace your SELECT statement with CASE expressions for retrieving the data and ranges with the following one:
From here on, just do everything the same as you currently are. The ranges should all show up in your PivotTable as they currently do.
Go to the SalaryRangeData table-row editor in SSMS again and delete the existing rows and then insert the following values: 0, 101, 201, 301, ... 2001 (again, order doesn't matter for the T-SQL solution). Go back to your PivotTable and refresh the data. And just like the Excel solution, the PivotTable ranges should be automatically changed.
Addition
HOW ADD IT TO A CUBE:
Connect to the Database, and add the
we only need customerId, as a measure for customer count and will have the same fact table as a dimension
if you need to change the Ranges, change the data in the
As requested this is an alternative to my previous answer that showed how to do it per-user with Excel. This answer shows how to do the same thing shared/centrally using T-SQL instead. I do not know how to do Cubes, MDX or the SSAS stuff for this, so maybe Benoit or someone who does know that can post its equivalent...
- Add SalaryRanges SQL Table and View
Create a new table called "SalaryRangeData" with the following command:
Create Table SalaryRangeData(MinVal INT Primary Key)Add calculated columns by wrapping it in a View with this command:
CREATE VIEW SalaryRanges As
WITH
cteSequence As
(
Select MinVal,
ROW_NUMBER() OVER(Order By MinVal ASC) As Sequence
From SalaryRangeData
)
SELECT
D.Sequence,
D.MinVal,
COALESCE(N.MinVal - 1, 2147483645) As MaxVal,
CAST(D.MinVal As Varchar(32))
+ COALESCE(' - ' + CAST(N.MinVal - 1 As Varchar(32)), '+')
As RangeVals
FROM cteSequence As D
LEFT JOIN cteSequence As N ON N.Sequence = D.Sequence + 1Right-click on the table in SSMS and select "Edit Top 200 Rows". Then enter the following values into the MinVal cells: 0, 501, 1001, and 2001 (order doesn't matter for SQL Server, it will create it for us). Close the table-row editor and do a
SELECT * FROM SalaryRanges to see all of the rows and range information.- Add AgeRanges SQL Table and View
Do the exact same steps as in #1 above, except replace all occurrences of "Salary" with "Age". This should make the table "AgeRangeData" and the view "AgeRanges".
Enter the following values into the AgeRangeData [MinVal] column: 0, 15, 20, 30, and 40.
- Add Ranges to The Data
Replace your SELECT statement with CASE expressions for retrieving the data and ranges with the following one:
SELECT [CustId]
,[CustName]
,[Age]
,[Salary]
,[SalaryRange] = (
Select RangeVals From SalaryRanges
Where [Salary] Between MinVal And MaxVal)
,[AgeRange] = (
Select RangeVals From AgeRanges
Where [Age] Between MinVal And MaxVal)
FROM [Customers]- Everything Else, The Same As Now
From here on, just do everything the same as you currently are. The ranges should all show up in your PivotTable as they currently do.
- Test The Magic
Go to the SalaryRangeData table-row editor in SSMS again and delete the existing rows and then insert the following values: 0, 101, 201, 301, ... 2001 (again, order doesn't matter for the T-SQL solution). Go back to your PivotTable and refresh the data. And just like the Excel solution, the PivotTable ranges should be automatically changed.
Addition
HOW ADD IT TO A CUBE:
- Create a View
CREATE VIEW CustomerView As
SELECT [CustId]
,[CustName]
,[Age]
,[Salary]
,[SalaryRange] = (
Select RangeVals From SalaryRanges
Where [Salary] Between MinVal And MaxVal)
,[AgeRange] = (
Select RangeVals From AgeRanges
Where [Age] Between MinVal And MaxVal)
FROM [Customers]- Create a a BI Project in Visual studio and add the
CustomerView
Connect to the Database, and add the
CustomerView View in the Data Source Views to be the Fact table- Create A cube and Define Measure & Dimension
we only need customerId, as a measure for customer count and will have the same fact table as a dimension
- Add Attributes to the Dimension
- Connect to Cube from Excel
- View the Data of the cube in the Excel
- for Any changes in the Ranges just reprocess the Dimension & cube
if you need to change the Ranges, change the data in the
SalaryRangeData and AgeRangeData and then just reprocess the dimensions and the cubeCode Snippets
Create Table SalaryRangeData(MinVal INT Primary Key)CREATE VIEW SalaryRanges As
WITH
cteSequence As
(
Select MinVal,
ROW_NUMBER() OVER(Order By MinVal ASC) As Sequence
From SalaryRangeData
)
SELECT
D.Sequence,
D.MinVal,
COALESCE(N.MinVal - 1, 2147483645) As MaxVal,
CAST(D.MinVal As Varchar(32))
+ COALESCE(' - ' + CAST(N.MinVal - 1 As Varchar(32)), '+')
As RangeVals
FROM cteSequence As D
LEFT JOIN cteSequence As N ON N.Sequence = D.Sequence + 1SELECT [CustId]
,[CustName]
,[Age]
,[Salary]
,[SalaryRange] = (
Select RangeVals From SalaryRanges
Where [Salary] Between MinVal And MaxVal)
,[AgeRange] = (
Select RangeVals From AgeRanges
Where [Age] Between MinVal And MaxVal)
FROM [Customers]CREATE VIEW CustomerView As
SELECT [CustId]
,[CustName]
,[Age]
,[Salary]
,[SalaryRange] = (
Select RangeVals From SalaryRanges
Where [Salary] Between MinVal And MaxVal)
,[AgeRange] = (
Select RangeVals From AgeRanges
Where [Age] Between MinVal And MaxVal)
FROM [Customers]Context
StackExchange Database Administrators Q#20099, answer score: 12
Revisions (0)
No revisions yet.