SSAS add measure value for some dimention value - ssas

I have fact table which looks like:
Fact Key, DIM ABC Key, AMOUNT, Other Dim Keys
1, 1, 0, ...
2, 2, 1, ...
3, 2, 2, ...
DIM ABC looks like:
DIM ABC Key, CODE, NAME
1, C1, N1
2, C2, N2
3, C3, N3
As You can see there is no fact for DIM ABC Key = 3 so I want to make some substitution by CODE:
SCOPE ([Measures].[AMOUNT], {[DIM ABC].[CODE].[C3]});
This = [Measures].[Count];
END SCOPE;
But this seems to work only if i have not selected DIM ABC Key.
Below is MDX which is working without CODE selected but it adds new measure what is unwanted:
CREATE MEMBER CURRENTCUBE.[Measures].[AMOUNT5] AS
IIF( [DIM ABC].[CODE].CURRENTMEMBER IS [DIM ABC].[CODE].[C3], [Measures].[Count], [Measures].[AMOUNT] )
, FORMAT_STRING = "Currency", VISIBLE = 1, ASSOCIATED_MEASURE_GROUP = 'FACT 1';
Should I start to play with LEAVES/DESCENDANTS or something in SCOPE?
I cannot do it by DIM Key becouse its surrogate key.
[Measures].[Count] is from other fact which has same dimention references and has value for C3.
Final data should behave like when You have fact as below:
Fact Key, DIM ABC Key, AMOUNT
1, 1, 0
2, 2, 1
3, 2, 2
4, 3, 1

Related

Query running total from week to week and use it to calculate row data

I have a table that stores Inventory Data by InventoryID and week. I need to somehow query and keep a running total of the DeltaQty from the prior weeks in order to figure out what is the Cumulative AvailQty for each week (Running total + AvailableQty)
CREATE TABLE InventoryWeekly (
StartDate date NULL,
EndDate date NULL,
InventoryID varchar(11) NULL,
AvailableQty float NULL,
OutgoingQty float NULL,
DeltaQty int NULL,
CumulativeAvailQty int NULL
);
INSERT INTO InventoryWeekly (InventoryID, StartDate, EndDate, OutgoingQty, AvailableQty, DeltaQty, CumulativeAvailQty)
VALUES
('00069','2023-01-09','2023-01-15', 1, 2, 1, 0),
('00069','2023-01-16','2023-01-22', 2, 2, 0, 0),
('00069','2023-01-23','2023-01-29', 3, 0, -3, 0),
('00071','2023-01-09','2023-01-15', 5, 8, 3, 0),
('00071','2023-01-16','2023-01-22', 2, 3, 1, 0),
('00071','2023-01-23','2023-01-29', 3, 1, -2, 0);
I've created this fiddle.
I've tried using LAG function but it isn't cumulative.
Let's start with
ALTER TABLE InventoryWeekly ADD CONSTRAINT InventoryWeekly_PK PRIMARY KEY CLUSTERED (StartDate)
It would help if you could describe what the output looks like.
A running total is just the sum of all previous values, which you can obtain as
SELECT iw.StartDate, iw.EndDate, iw.InventoryID, iw.AvailableQty, iw.OutgoingQty, iw.DeltaQty,
SUM(h.AvailableQty) AS TotalPreviousAvailableQuantity
FROM InventoryWeekly iw
LEFT JOIN InventoryWeekly h ON iw.StartDate > h.StartDate
GROUP BY iw.StartDate, iw.EndDate, iw.InventoryID, iw.AvailableQty, iw.OutgoingQty, iw.DeltaQty

Choose a record from the table where two of the default values are 0 or 1, a bit tricky

Looking for a more elegant and most logical solution for:
The table:
index
id
by_default
text
1
1
0
AAA
2
1
1
ABA
3
1
0
ABC
4
2
0
BCA
5
2
0
BCB
The task is to find the minimum index value with defaults set to 1 and/or defaults set to 0.
I have the following code (not very elegant, but it works, also very slow):
declare #byd_1 as int=
(select min(t.index) idx from Table t where t.[id]=1 and t.by_default=1)
declare #byd_2 as int=
(select min(t.index) idx from Table t where t.[id]=1 and t.by_default=0)
select (case when #byd_1 is null then #byd_2 else #byd_1 end)
The tricky part is: sometimes the by_default column is always 0 (for example: id:2 may have no by_default values set) and as mentioned earlier the task is: need to get the minimum value of the index column.
What is the most elegant (one-line) code possible?
Using MSSQL
The expected results, according to the sample table, should be the following:
index
id
by_default
text
2
1
1
ABA
4
2
0
BCA
Edited to add text also.
A bit ugly but:
drop table #t
select *
into #t
from (
VALUES (1, 1, 0, N'AAA')
, (2, 1, 1, N'ABA')
, (3, 1, 0, N'ABC')
, (4, 2, 0, N'BCA')
, (5, 2, 0, N'BCB')
) t (index_,id,by_default,text)
select index_, id, by_default, text
from (
select min(index_) OVER(PARTITION BY id) AS minIndex
, MIN(case when by_default = 1 then index_ end) over(partition by id) AS minIndexDefault
, *
from #t
) t
where isnull(minIndexDefault, minIndex) = index_

Refer to the calculated column within the column

Column ORtg_home contains values differ from zeros and zeros. My purpose is to create a new column (X) in which there are only values without zeros. (After the first home game. If it would be a zero then give back the last value which is not zero from ORtg_home).
Team
Game_total
Home_away
Game_home
Game_away
ORtg_avg
ORtg_home
x
ATL
1
away
0
1
100
0
0
ATL
2
home
1
1
101
102
102
ATL
3
away
1
2
104
0
102
ATL
4
away
1
3
106
0
102
I tried the code below:
SELECT
[ORtg_home]
,(CASE WHEN [Home_away] = 'home' THEN ([ORtg_home])
ELSE
LAG(ORtg_home, 1) OVER (PARTITION BY Team ORDER BY [Game_total] ASC, Home_away ASC) END) as XXX
FROM [table1]
This gives 102 for the 3rd game, however the 4th game value in column x is still 0. Teams may vary. Currently table does not contain the date of the game, but it can be added.
CREATE TABLE [test1]
(
[Team] VARCHAR(3)
,[Game_total] INT
,[Home_away] VARCHAR(4)
,[Game_home] INT
,[Game_away] INT
,[ORtg_avg] FLOAT
,[ORtg_home] FLOAT
,[x] FLOAT
)
INSERT INTO [test1]
[Team], [Game_total], [Home_away], [Game_home], [Game_away, [ORtg_avg] ,[ORtg_home]
VALUES (ATL, 1, 'away', 0, 1, 100, 0)
VALUES (ATL, 2, 'home', 1, 1, 101, 102)
VALUES (ATL, 3, 'away', 1, 2, 104, 0)
VALUES (ATL, 4, 'away', 1, 3, 106, 0)
This would be easier if LAST_VALUE supported the IGNORE_NULLS clause as then you could just convert the zeroes to NULL and use that.
In the absence of this you can use the approach below (fiddle)
WITH T AS
(
SELECT *,
MAX(FORMAT(Game_total,'D10') + FORMAT(NULLIF(ORtg_home,0),'R')) OVER (PARTITION BY Team ORDER BY [Game_total] ASC) AS _x
FROM test1
)
SELECT Team,
Game_total,
Home_away,
Game_home,
Game_away,
ORtg_avg,
ORtg_home,
COALESCE(SUBSTRING(_x, 11, 100), 0E0) AS x
FROM T

How to get the rows that are an error with their latest sequence?

The objective is to get the rows that are an error with their latest sequence. sample data as follows, Temptable is used since it useful for further transactions
here is my query
SELECT MAX(cc.[sequence]) [sequence],
OrderID,
OrderItemID
INTO #tmpErrorRecords
FROM [TMC].CVOrderCompletions cc
WHERE cc.[status] = 0
AND LTRIM(RTRIM(ISNULL(errorMessage, ''))) <> ''
GROUP BY cc.OrderID,
cc.OrderItemID;
My lead reviews the above query and says, There is still going to be a bug in the way you are selecting the error rows in the temp table. I have revised the code that selects the error rows and it should look like below.
But I'm wondering what is the difference between the above and the revised query? Appreciate if somebody could help me with this please
SELECT MAX(cc.[sequence]) [sequence],
OrderID,
OrderItemID
INTO #tmpOCRecords
FROM TMC.CVOrderCompletions cc
GROUP BY cc.OrderID,
cc.OrderItemID;
SELECT cc.[sequence],
cc.OrderID,
cc.OrderItemID
INTO #tmpErrorRecords
FROM TMC.CVOrderCompletions cc
INNER JOIN #tmpOCRecords tc ON(cc.OrderID = tc.OrderID
AND cc.OrderItemID = tc.OrderItemID
AND cc.[sequence] = tc.[sequence]
AND LTRIM(RTRIM(ISNULL(cc.errorMessage, ''))) != ''
AND cc.STATUS = 0);
What your lead could/should have told you is that cc.[status] = 0 is not going to fetch any rows for the shown sample data...
What defines an error row? It has an error message.
This is the only filter you need. Do not overcomplicate things.
Sample data
(Text data that can be copy-pasted instead of images next time, please!)
create table tmpErrors
(
id int,
orderId int,
orderItemId int,
sequence int,
status int,
errorMessage nvarchar(100)
);
insert into tmpErrors (id, orderId, OrderItemId, sequence, status, errorMessage) values
( 1, 1136832, 1, 0, 1, null),
( 2, 1136832, 1, 1, 1, null),
( 3, 1142898, 1, 0, 1, 'Sql procedure ...'),
( 4, 1142898, 1, 1, 1, 'Sql procedure ...'),
( 5, 1142898, 1, 2, 1, 'Sql procedure ...'),
( 6, 1142898, 1, 3, 1, 'Sql procedure ...'),
( 7, 1142904, 1, 0, 1, null),
( 8, 1142910, 1, 0, 1, 'Invoice record ...'),
( 9, 1142910, 1, 1, 1, 'Invoice record ...'),
(10, 1142910, 1, 2, 1, 'Invoice record ...'),
(11, 1142916, 1, 0, 1, null);
Solution
select te.orderId,
te.orderItemId,
max(te.sequence) as sequence
from tmpErrors te
where te.errorMessage is not null
group by te.orderId,
te.orderItemId;
Result
orderId orderItemId sequence
------- ----------- --------
1142898 1 3
1142910 1 2
Fiddle to see things in action.

How to rename items by assigning sequential number?

I have the following table:
DECLARE #OperatorPrice TABLE
(
ID INT NOT NULL, DealerId INT NULL, DealerName VARCHAR(50) NULL
)
and sample data:
INSERT INTO #OperatorPrice
(
ID, DealerId, DealerName
)
VALUES
(226, 1, 'WestCarDealer')
, (112, 1, 'WestCarDealer')
, (266, 2, 'AO')
, (112, 2, 'AO')
, (93, 3, 'Best on the West')
, (93, 3, 'Best on the West')
What I want is to rename all dealers to 'Dealer1', 'Dealer2', 'Dealer3'. The number should be assigned in ascending order: AO should be renamed to 'Dealer1' cause AO starts with A, Best on the West should be renamed to Dealer2 cause it starts with B, WestCarDealer should be renamed to Dealer3 cause it starts with W.
So the desired output should looks like this:
(226, 1, 'Dealer3')
, (112, 1, 'Dealer3')
, (266, 2, 'Dealer1')
, (112, 2, 'Dealer1')
, (93, 3, 'Dealer2')
, (93, 3, 'Dealer2')
Approximate quantity of unique DealerName's is 50 dealers.
How can I rename car dealers in that way?
I've tried to use cursors for this purpose, but could not store the number to increment.
You can use an CTE to update the table variable
Example
;with cte as (
Select *
,NewVal = concat('Dealer',dense_rank() over ( order by DealerName))
From #OperatorPrice
)
Update cte Set DealerName = NewVal
Updated #OperatorPrice
ID DealerId DealerName
226 1 Dealer3
112 1 Dealer3
266 2 Dealer1
112 2 Dealer1
93 3 Dealer2
93 3 Dealer2