MDX How to add bands to grouped fact table - range

I'm trying to create income bands on my fact table.
The fact table that consists of
Date, TranType, AdvKey, Amount
01/01/2015 TRAN1 ID01 5000
01/02/2015 TRAN1 ID02 13000
01/03/2015 TRAN2 ID01 500
The AdvKey links back to DimIFADetails, this table has a ParentKey, a Parent Child hierarchy. There are two levels, Adviser and Adviser Group
ADVKEY PARENTKEY
----------------
ID01 ID03
ID02 ID03
ID03 NULL
I want to be able to group on AdvKey or AdvGrpKey and have the summed amounts (income) allocated to income bands.
So when I group on Adviser, each adviser will be assigned an income band, ie 0-10k, 10-50k, 50-100k, same applies when the grouping is changed to the Group Level.
In the above
ID01 5300 0-10000
ID02 13000 10000-20000
or if by Adviser Group
ID03 18300 10000-20000
In SQL, I could group by the key necessary, then add a column and case statement to allocate each aggregated amount to a band.
The facttable has about 2 million rows.
The income is how much is generated from the advisers and adviser group, so this will change over time.
I can't think of any way to do it with a dimension, as there is no way to link back to the fact table seeing as these are groupings done at run time.
I now have something that works
with
MEMBER Measures.[Calc Sum] as
IIF( Sum(EXISTING [Dim IFA Details].[Parent Key].[Adviser Group].Members,
Measures.[Amount] * -1
) <= 10000 , '0-10000', IIF( Sum(EXISTING [Dim IFA Details].[Parent Key].[Adviser Group].Members,
Measures.[Amount] * -1
) <= 20000 , '10001 - 20000' , '>20000' ))
SELECT { [Measures].[Amount] , measures.[Calc Sum] }
ON COLUMNS,
NONEMPTY( [Dim IFA Details].[Parent Key].[Adviser Group].Members , [Measures].[Amount])
on rows
FROM [Income and Emails Cube]
Its going to have a rather bulky IIF when I add more bands.
Is it possible to create a dimension with the categories and add the keys on the fly like this?
or would there be no benefit.

Related

ERROR CODE 1241 :OPERAND SHOULD CONTAIN 1 COLUMN(S)

My goal is to retrieve all accounts where the balance is greater than zero.
I have two table the tblloancontract and the tblloanpayment.
tblloancontract has two columns: accnum, and idmember.
tblloanpayment has: idpayment, balance, and accnum (a foreign key from tblloancontract).
Below is the MYSQL code I have written so far:
SELECT * FROM tblloanpayment WHERE accnum IN
(SELECT MAX(idpayment), tblloanpayment.accnum, MIN(tblloanpayment.balance)
FROM tblloanpayment JOIN tblloancontract ON tblloanpayment.accnum=tblloancontract.accnum
GROUP BY idmember) AND balance > 0;
Don't you just want all accounts where the lowest balance is greater than 0? In that case, why do you need the tblloancontract table at all?
SELECT tlp.accnum, MIN(tlp.balance)
FROM tblloanpayment tlp
GROUP BY tlp.accnum
HAVING MIN(tlp.balance) > 0;
That's not really a very good way to store loan information. The "contract" table should have the initial balance and the current balance, and the "payment" table should have the payment amounts.

High Value at Each Granularity

I have an table below which shows some data and I am trying to get the high value from each row.
Below is the data I have:
Table A
Once calculated it should looks like below in tableau
Table B
Notice that for Total, its not summing up from pers and bus instead its getting it highest value from total from table A and same concept is for Grand Total. Numbers which you see are balance.
I am able to get high value up to Total but its the grand total where I am struggling with. Below is my Calculation which I am using.
if
countd([Category]) = 1 then
sum({ FIXED [Group], [Category]: max(
{ FIXED [Group], [Category], [Date]: SUM([Balance])})})
ELSE
sum({ FIXED [Group]: max(
{ FIXED [Group], [Date]: SUM([Balance])})}
)
END
Step-1: For max of categories, use this calculation desired maximums
MAX({Fixed [MVRA Group], [Product Category], [Date Display]: ([Primary Measure])})
STEP-2: For max of subtotal, use desired sub-total maximum
MAX({Fixed [MVRA Group], [Date Display]: ([Primary Measure])})
https://drive.google.com/file/d/1zyjCDdG_QECrkFgY-UFm7WM2yN1xaHmZ/view?usp=sharing

PostgreSQL product table and sales table

I have the following problem.
I need all the products in a table and at the same time put the sum of the quantities sold of each product.
I need to see each product in the product table with the total sum of sales, according to the date range.
If there is no sales record in that range, it must be zero.
My query is as follows, but it doesn't work.
Product Table : sto_producto
Product sales movement table: sto_movdet
SELECT
sto_producto.pro_codprod AS cod_product,
sto_producto.pro_desc AS name_product,
sum(sto_movdet.mvd_cant) AS total_sale,
AVG(sto_movdet.mvd_costo) AS cost_product_sale
FROM sto_producto
INNER JOIN sto_movdet ON (sto_producto.pro_codprod = sto_movdet.mvd_codprod)
WHERE mvd_fecha BETWEEN '2020301' and '20200716'
GROUP BY pro_codprod, pro_desc
I expect a result similar to
cod_product name_product total_sale cost_product_sale
0004 mousered 45 $ 2.355
0071 pc laptop 0 $ 1.000

Indicate more than one record with matching fields

How can I indicate multiple records with the same Invoice number, but a different Sales Person ID? Our commissions can be split into multiple Salespeople, so there can be two different Salespeople per an invoice.
For example:
Grouped by: Sales Person ID (No Changing this option)
These records are in the Group Footer.
Sales Person ID: Invoice: Invoice Amt: Commissions: (Indicator)
4433 R100 20,000 3,025 * More than one record on the same invoice with a different sales person
4450 R096 1,987 320
4599 R100 20,000 3,025 * More than one record on the same invoice with a different sales person
4615 R148 560 75
4777 R122 2,574 356
If your report has less than 1000 invoices, you may try something like this.
This will return true when a second ocurrence of the invoice shows up. Then you can make something like set the row background do red.
Global NumberVar Array invoices;
numbervar nextIndex := count(invoices) + 1;
if nextIndex <= 1000 and not ({Result.InvoiceNumber} in invoices) then (
redim invoices [nextIndex];
invoices[nextIndex] := {Result.InvoiceNumber};
true;
)
else false;
If you want to detect the first occurrence, you will need something more sophisticated.
I think a SQL Expression Field would be a good way to achieve the result you want. You already have an InvoiceNo in each row of data. You just need a SQL Expression Field that uses that INvoiceNo to execute a query to count the number of salespersons who get a commission.
Something along the lines of:
(
Select Count(Sales_Person_Id)
From [Table]
Where [Table].InvoiceNo = InvoiceNo
)
This will return an integer value that represents the number of salespersons who are associated with one invoice. You can either drop the SQL Expression Field in your Indicator column, or write some other formula to do something special.

T-SQL Query to process data in batches without breaking groups

I am using SQL 2008 and trying to process the data I have in a table in batches, however, there is a catch. The data is broken into groups and, as I do my processing, I have to make sure that a group will always be contained within a batch or, in other words, that the group will never be split across different batches. It's assumed that the batch size will always be much larger than the group size. Here is the setup to illustrate what I mean (the code is using Jeff Moden's data generation logic: http://www.sqlservercentral.com/articles/Data+Generation/87901)
DECLARE #NumberOfRows INT = 1000,
#StartValue INT = 1,
#EndValue INT = 500,
#Range INT
SET #Range = #EndValue - #StartValue + 1
IF OBJECT_ID('tempdb..#SomeTestTable','U') IS NOT NULL
DROP TABLE #SomeTestTable;
SELECT TOP (#NumberOfRows)
GroupID = ABS(CHECKSUM(NEWID())) % #Range + #StartValue
INTO #SomeTestTable
FROM sys.all_columns ac1
CROSS JOIN sys.all_columns ac2
This will create a table with about 435 groups of records containing between 1 and 7 records in each. Now, let's say I want to process these records in batches of 100 records per batch. How can I make sure that my GroupID's don't get split between different batches? I am fine if each batch is not exactly 100 records, it could be a little more or a little less.
I appreciate any suggestions!
This will result in slightly smaller batches than 100 entries, it'll remove all groups that aren't entirely in the selection;
WITH cte AS (SELECT TOP 100 * FROM (
SELECT GroupID, ROW_NUMBER() OVER (PARTITION BY GroupID ORDER BY GroupID) r
FROM #SomeTestTable) a
ORDER BY GroupID, r DESC)
SELECT c1.GroupID FROM cte c1
JOIN cte c2
ON c1.GroupID = c2.GroupID
AND c2.r = 1
It'll select the groups with the lowest GroupID's, limited to 100 entries into a common table expression along with the row number, then it'll use the row number to throw away any groups that aren't entirely in the selection (row number 1 needs to be in the selection for the group to be, since the row number is ordered descending before cutting with TOP).