I created an SSAS Tabular model using the AdventureWorksDW database.
I used the post below to help me build the report.
https://blog.gbrueckl.at/2014/02/applied-basket-analysis-in-power-pivot-using-dax/
Sold in same Order:=
CALCULATE (
COUNTROWS ( 'Internet Sales' ),
CALCULATETABLE (
SUMMARIZE (
'Internet Sales',
'Internet Sales'[SalesOrderNumber]
),
ALL ( 'Product' ) ,
USERELATIONSHIP( 'Internet Sales'[ProductKey],FilteredProduct[ProductKey])
)
)
I have validated that the results from the formula are correct. There are 1,381 orders with the Touring Tire Tube sold and shows me how many orders were sold with the other items (e.g. 170 out of the 1,381 orders also included product key 214 - Sport-100 Helmet, Red).
Here is where I'm having an issue. I would like to summarize my data by showing how many of the orders only included my filtered items vs. orders sold with other products. This has to be dynamic since users can select any products... The end result should look like this:
I'm new to DAX and have struggled with this for a few hours. Thanks for your help.
Here is the table relationship:
this DAX should work on the example dataset from my blog:
Orders with only the filtered products =
--VAR vFilteredProducts = VALUES('Filtered Product'[ProductKey])
VAR vFilteredProducts = FILTER('Filtered Product', [ProductKey] = 530 || [ProductKey] = 541)
VAR vCountFilteredProducts = COUNTROWS(vFilteredProducts)
VAR vSales = CALCULATETABLE('Internet Sales', -- get the Sales for the filtered Products
vFilteredProducts,
USERELATIONSHIP('Filtered Product'[ProductKey], 'Internet Sales'[ProductKey]),
ALL('Product'))
VAR vOrders = SUMMARIZE( -- Summarize the filtered product sales by Sales Order Number
vSales,
[Sales Order Number],
-- calucate the distinct filtered products in the filtered orders
"CountFilteredProductsInOrder", CALCULATE(DISTINCTCOUNT('Internet Sales'[ProductKey])),
-- calculate the all distinct products for the filtered orders
"CountTotalProductsInOrder", CALCULATE(DISTINCTCOUNT('Internet Sales'[ProductKey]),
ALLEXCEPT('Internet Sales', 'Internet Sales'[Sales Order Number]))
)
RETURN COUNTROWS(
FILTER(
vOrders,
-- the total product count has to match the filtered product count --> no other products except filtered ones in order
[CountFilteredProductsInOrder] = [CountTotalProductsInOrder]
)
)
To get the orders where also other products except the filtered ones were sold, imply change the last FILTER() from '=' to '<'
Related
I'm struggling to create a DAX query to get the weekly sales amount and total sales amount (sum of all weeks together) on a same row. I'm filtering on item and year.
Example of a query:
EVALUATE
SUMMARIZECOLUMNS(
Artikel[ART Artikel],
Datum[Jahr-Woche],
FILTER (
Artikel,
Artikel[ART ArtikelNr]="222834"
),
FILTER (
'Datum',
Datum[Jahr]="2022"
),
"Sales Quantity ", [VK Menge],
"Sales Quantity Total", CALCULATE([VK Menge], ALL(Datum[Jahr-Woche]) )
)
The Sales Quantity Total doesn't return the yearly total - it returns the same value as Sales Quantity. It seems that the ALL() function is not removing the filter from the column Datum[Jahr-Woche]):
I've tried using REMOVEFILTERS(), etc. to no success.
What am I doing wrong?
Note 1:
When I remove the filtering on Datum[Jahr] from the query, the ALL() function starts working - the Sales Quantity Total returns the total sum. However - I need to filter on the year in the query... This behaviour is very confusing. :(
EVALUATE
SUMMARIZECOLUMNS(
Artikel[ART Artikel],
Datum[Jahr-Woche],
FILTER (
Artikel,
Artikel[ART ArtikelNr]="222834"
),
"Sales Quantity ", [VK Menge],
"Sales Quantity Total", CALCULATE([VK Menge], ALL(Datum[Jahr-Woche]) )
)
Please try this code and let me know If It works for you! Calculate evaluates external filters first, then internal filters!
YourMeasure =
SUMMARIZECOLUMNS (
Artikel[ART Artikel],
Datum[Jahr-Woche],
FILTER ( Artikel, Artikel[ART ArtikelNr] = "222834" ),
"Sales Quantity ", [VK Menge],
"Sales Quantity Total",
CALCULATE (
CALCULATE ( [VK Menge], Datum[Jahr] = "2022" ),
ALL ( Datum[Jahr-Woche] )
)
)
EXPLAIN Above Same Code:
I've come across this DAX measure:
# CustMultProds =
COUNTROWS(
FILTER(
Customer,
CALCULATE( DISTINCTCOUNT( Sales[ProductKey] ) ) >= 2
)
)
I pretty much understand how it works - it iterates over Customer inside the FILTER function, then the row context created by this iterator is transitioned into a filter context so that it is able to get the number of distinct products from the Sales table.
I am wondering is it possible to re-write the measure without using CALCULATE ? I got as far as using RELATEDTABLE but then not sure how to extract the distinct ProductKeys from each related table:
# CustMultProds =
COUNTROWS(
FILTER(
Customer,
RELATEDTABLE (Sales)
...
...
)
)
This is a possible implementation of the measure using RELATEDTABLE. But Context Transition still happens once per customer because RELATEDTABLE performs a context transition
# CustMultProds =
COUNTROWS(
FILTER(
Customer,
VAR CustomerSales =
RELATEDTABLE( Sales )
RETURN
MAXX( CustomerSales, Sales[ProductKey] )
<> MINX( CustomerSales, Sales[ProductKey] )
)
)
This is another way to write a measure leveraging RELATEDTABLE, that could be modified to deal with a different number of distinct products
# CustMultProds =
COUNTROWS(
FILTER(
Customer,
COUNTROWS( SUMMARIZE( RELATEDTABLE( Sales ), Sales[ProductKey] ) ) >= 2
)
)
This is another possible implementation, without CALCULATE and RELATEDTABLE.
But it scans the entire Sales table once per customer, so, even if it doesn't perform a context transition I'd expect it to be slower
# CustMultProds =
COUNTROWS(
FILTER(
Customer,
VAR SalesProducts =
SUMMARIZE( Sales, Sales[CustomerKey], Sales[ProductKey] )
RETURN
COUNTROWS(
FILTER( SalesProduct, Sales[CustomerKey] = Customer[CustomerKey] )
) >= 2
)
)
I have a working query using the PIVOT function but I am wondering if I have to define all values I want to see as column headers. Here is what I have:
select * from
(
SELECT ID, product, notebal
from accounts
where (accounts.effdate = ( Select MAX(EFFDATE) FROM accounts))
)
PIVOT
(
SUM(notebal) for product in ('NAID','UAID','SVGS','DRFT')
)
Order by 3 desc
There are 28 different products. Do I have to define all 28 in the "for product in()" statement?
I want to create a topcount of users per product category.
My product dimension is like the following [Product].[ProductCategory].[ProductType] Users of my application can filter the products and it return a set like this: [Product].[ProductCategory1].[ProductType1], [Product].[ProductCategory3].[ProductType5], ...
Now I got the topcount per product category, but it doesn't filter the children of the category: the types. Example of my query:
SELECT
NON EMPTY {[Measures].[Orders]} ON COLUMNS,
NON EMPTY
{Order(
Generate(
Exists(
[Product].[ProductCategory].Members
,{
[Product].[ProductCategory1].[ProductType1]
,[Product].[ProductCategory3].[ProductType5]
}
)
, TopCount(
Crossjoin(
{[Product].[ProductCategory].currentmember}
,{[USER].[UserName].Members}
)
,5.0
,[Measures].[Orders]
)
)
, [Measures].[Orders]
, DESC
)
} ON ROWS
FROM [Products]
The [Product].[ProductCategory].currentmember doesn't return the category with filtered product types.
Does anyone have a solution?
(Not an answer but a script to hopefully help find the answer)
I'm guessing your question is in connection with the Exists section of the script. Does this return a result you expect?
SELECT
{[Measures].[Orders]} ON COLUMNS,
Exists(
[Product].[ProductCategory].Members
,{
[Product].[ProductCategory1].[ProductType1]
,[Product].[ProductCategory3].[ProductType5]
}
)
ON ROWS
FROM [Products]
I fixed my problem using a calculated measure to filter the measure with the product members.
WITH MEMBER [Measures].[FilteredOrders] AS
'SUM(exists([Product].[ProductCategory].currentmember.children, {[Product].[ProductCategory1].[ProductType1]
,[Product].[ProductCategory3].[ProductType5]}), [Measures].[Orders])'
I have a question about Linq select statement. I am new to Linq so any help will be very helpful. I did a lot of research but I still didn't manage to write down correct Linq statement.
I have this two tables and attributes:
Table Titles(title_id(PK), title) and
Table Sales(title_id(PK), qty)
where are title_id and title string values and qty is a number which represents some quantity.
I need to write a select which will take five most selling titles from this two tables.
So, I need to make sum from qty (we can have more records with the same Sales.title_id attribute) and make group by title_id and order by sum(qty) descending and then return attributes title and title_id.
How can I make suitable solution for my question?
Regards,
Dahakka
You can do group join of tables by title_id (each group g will represent all sales of joined title). Then select title description and total of sales for that title. Order result by totals, select title and take required number of top sales titles:
var query = (from t in db.Titles
join s in db.Sales on t.title_id equals s.title_id into g
select new { Title = t.title, Total = g.Sum(x => x.qty) } into ts
orderby ts.Total descending
select ts.Title).Take(5);
Resulting SQL will look like:
SELECT TOP (5) [t2].[title] AS [Title], [t2].[value] AS [Total]
FROM (
SELECT [t0].[title_id], (
SELECT SUM([t1].[qty])
FROM [Sales] AS [t1]
WHERE [t0].[title_id] = [t1].[title_id]
) AS [value]
FROM [Titles] AS [t0]
) AS [t2]
ORDER BY [t2].[value] DESC
Following is the linq query in method syntax
sales.GroupBy(s=>s.title_id)
.Select ( x =>
new {
Title_id = x.Key,
Sales= x.Sum (x=> x.qty)
})
.OrderByDescending(x=>x.Sales).Take(5)
.Join( titles,
sale=>sale.Title_id,
title=> title.title_id,
(sale, title)=> new
{
Title = title.Title,
TotalSales=sale.Sales
}
);