I have DimProduct table, DimCustomer table and FactSales table.
There is a targeted product list.
I want to list customers who buy all products of the targeted product list in one invoice.
How do I do it? I have no clue. Please give me some advice.
CustomersWithAllTargets:=
COUNTROWS(
FILTER(
DimCustomer
,CALCULATE(
DISTINCTCOUNT( FactSale[ProductKey] )
,TargetProduct
) = DISTINCTCOUNT( TargetProduct[ProductKey] )
)
)
Let's break this down.
COUNTROWS() does what it says and counts the rows in a table.
The table whose rows we want to count is the result of our FILTER(). FILTER() takes a table expression as its first argument, creating a row context by iterating over each row in that table expression. For each row, the expression in its second argument is evaluated. Only those rows in the table for which the second argument evaluates to true are included in the output.
Our table argument is DimCustomer. DimCustomer will be filtered by the pivot's filter context (e.g. if you select a subset of customers, only that subset will be considered).
For each customer, we evaluate the CALCULATE().
CALCULATE() evaluates its first argument in the filter context defined by its second through last arguments. We're counting the distinct values in FactSale[ProductKey] for the current customer (current in the iteration through each row from FILTER()), subject to the constraint that they exist in the table TargetProduct.
We are testing the value of that CALCULATE() (how many target products the current customer has bought), with the count of values in TargetProduct[ProductKey]. When they are equal, the customer has bought all products. When they are not equal, the customer hasn't.
So we'll return a table of customers who've bought all the target products. At the customer level in a pivot, this will return 1 or blank for each customer. Pivot tables automatically suppress the display of row labels with blanks for measures, so you'll only see the customers that have bought all the target products.
The grand total will tell you how many customers total have bought all the targets.
This will also support selecting subsets of TargetProduct, if you have different target groups.
Below is an image of my model and sample data, along with a pivot table showing the whole thing behaving appropriately.
Edit
We'll make use of one more function to be able to group by multiple fields, SUMMARIZE().
CustomersWithAllTargets:=
COUNTROWS(
FILTER(
SUMMARIZE(
FactSale
,FactSale[InvoiceKey]
,FactSale[CustomerKey]
)
,CALCULATE(
DISTINCTCOUNT( FactSale[ProductKey] )
,TargetProduct
) = DISTINCTCOUNT( TargetProduct[ProductKey] )
)
)
SUMMARIZE() takes a table as its first argument and a list of fields to group by. It can also add calculated columns and do rollups on those columns, but we don't need that. Newer versions of Power Pivot (Excel 2016) have a syntax-equivalent GROUPBY() that performs grouping for a potential (small) performance improvement. We simply group on InvoiceKey and CustomerKey and do the same filtering as before.
This does alter the nature of the return value. Previously the count would be the number of customers who've purchased the whole set of target products. Since we're now also grouping on invoice, the count will be of the number of customer-invoice pairs that have all targets purchased. Since your requirement was stated simply as listing the customers, this measure still meets them. You may see a number >1 for a specific customer, though. You will still have the behavior in a pivot of omitting the customers who don't meet the criteria.
Here's a picture of my altered sample data performing with this measure. Note that Customer6 now has purchased all three targets, but on separate invoices. Customer3 still shows up as all three are on 1 invoice.
Related
I am writing a SQL query that needs to show the total number of orders from each store. The issue I am running into, is that while I can figure out how to sum the orders by product and each product is only sold by one store, I can't figure out how to total the orders by store alone
This is the code I currently have
SELECT storeID AS [STORE], Product_ID
, SUM(quantity) AS [ORDERS BY STORE]
FROM Fulfillment, Store
GROUP BY storeID, Product_ID;
This line of code leads to a repeat of storeID in the results, where ideally, I would only want storeID to be included in the results once with the total quantity of all of Product_ID being included. I tried to remove Product_ID from the GROUP BY statement, but this resulted in the following error
Column 'Fulfillment.Product_ID' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
I'm new to SQL and am trying to learn, so any help and advice is greatly appreciated
#ZLK is correct that if your goal is a total number of units ordered ("quantity") of any product, simply remove the [product_id] column from the SELECT and GROUP BY.
However, it appears that you're referencing two tables ("FROM Fulfillment, Store") and not specifying how those tables are joined, creating a cartesian join - all rows in one table will be joined to all rows in the other table. If the [storeID] and [quantity] fields are available in the Fulfillment table, I recommend removing the Store table reference from the FROM clause (so "FROM Fulfillment" alone).
One last note: You mention that you want to count "orders". In some circumstances, an order may have multiple products and a quantity > 1. If your goal is the total number of "orders" regardless of the number of products or quantity of products on an order, you'll want to use "COUNT(DISTINCT orderID) as [Orders]" (where "orderID" is the reference to the unique order number).
I have a list of my stock in one table, stock, and I reserve portions of that stock to an order in another table, orders
I have a feeling my data is no longer in a good state, and I need to compare the amount I have reserved from a chunk of stock in the orders table to the total I have in the reserved stock table.
Each stockref has a unique entry in stock but can occur multiple times in orders if it represents a quantity that is split across multiple orders.
The ideal query would show me stockrefs that are over-reserved. Once I have these I can then check my code to see what caused the issue and fix it before I go bust selling items I no longer have stock of.
I think this should resolve your problem
Select s.reservedqty,s.stockref,O.Total_reservedqty from stock S join
(
Select sum(reservedqty) as Total_reservedqty,stockref from orders group by stockref
) O
On S.stockref=O.stockref
where O.Total_reservedqty !=s.reservedqty
with regard to the following question and the given response I have the following question:
I am facing the same issue, but creating a bridge table like mentioned above is no option in my case as I still need the separate dimensions for other operations and different analysis.
For budgeting reasons I have to show all customers even if they have no match with the fact table. Enabling the corresponding option in EXCEL obiously leads to a cross join of the selected dimensions resulting in a complete list of all customers in all countries, although not each customer exists in all countries.
Is there another altrnative to force SSAS respecting relationships defined?
Many thanks in advance for assistance.
Let’s say you have FactSales with CustomerKey, CountryKey, DateKey and SalesAmount. When you build a PivotTable in Excel with Customer and Country on rows and SalesAmount on columns it only shows customers with sales. If you set Excel to show rows with no data it shows all customers in all countries.
Try building a new FactCustomerCountry table with CustomerKey and CountryKey only. Create a measure Customer Country Count.
Then create a new calculated measure:
CREATE MEMBER CURRENTCUBE.[Measures].[Sales Amount with Zeros]
AS
IIF(
IsEmpty([Measures].[Customer Country Count]),
Null,
CoalesceEmpty([Measures].[SalesAmount], 0)
);
Use that measure in your PivotTable instead of SalesAmount. Do not show rows with no data. The measure should return meaningful Customer-Country combinations and should return all customers.
Hi you can solve your issue in MDX. Take a look at the query below, its an example on Adventureworks. This will fetch all the products that were sold and the quaters that they were sold in.Now some products were never sold, I still want to see those product.
select [Measures].[Internet Sales Amount] on columns,
--non empty
{filter(([Product].[Subcategory].[Subcategory],[Date].[Calendar Quarter of Year].[Calendar Quarter of Year]),[Measures].[Internet Sales Amount]>0),
filter(([Product].[Subcategory].[Subcategory],[Date].[Calendar Quarter of Year].defaultmember),[Measures].[Internet Sales Amount]=null)
}
on rows
from
[Adventure Works]
this is my first question on here, so please forgive me if I break any rules.
Here is what I need to know:
How do I create an Oracle SQL query that will display a unique count of something even if there are duplicates in the results?
Example: a customer table has a list of purchases made by various customers. The table lists the customer ID, name, category of purchase (ie Hardware, Tools, Seasonal) ect. The outcome of the query needs to show each customer id, customer name and the category of the purchase, and a count of the individual customer. SO customer ID 1 for John Smith has made a purchase in each department. If I do a count of the customer, he will appear three times as he has made three purchases, but I also need a column to count the customer only once. The count in the other rows returned for the other departments should show a 0 or Null.
I normally achieve this by pulling everything and exporting to excel. I add a column that uses an IF formula on the ID to only show a 1 on the first occurrence of the customer IE: IF(A3=A2,0,1) (if a3 is the same as A2, show a 0, if it's not the same as A2 then show a 1). This will give me a unique count of customers for one part of the report and will still show me how many purchase the customer made in another part of the report.
I want to do this directly in the SQL query as I have a large set of data this needs to be done on, and adding any formulas in excel will make the sheet huge. This will also make it easier to host the query results in ACCESS so excel can pull it from there.
I have tried to find a solution to this for a while, but any searching on Google will usually return results on how to remove duplicates form a table or how to count the duplicates in a table.
I am sorry if this is long question, but I wanted to be through so I do not waste anyone's time on back an fourth comments (I have seen this many times on here and else where when the OP asks a very cryptic question and expects everyone to understand them without further expiation).
Using distinct can be used in a count to only count the unique values of a field.
SELECT
cust.customer_id, cust.customer_name, p.category,
count(distinct p.department_id) as total_departments,
count(*) as total_purchases
FROM customers cust
LEFT JOIN purchase_table p on (cust.customer_id = p.customer_id)
GROUP BY cust.customer_id, cust.customer_name, p.category
ORDER BY cust.customer_id;
Such method is not limited to the Oracle RDBMS.
I am working on a database with products and lot numbers. Each entry in the Lots table has a Lot Number and a Product description.
Sometimes there are multiple records of the same lot number, for example when an item is repacked a new record is created, but with the same Lot Number and same product description - this is fine. But other times there are problem cases, namely when two different products share the same Lot Number. I am trying to find those.
In other words, there are 3 possibilities:
Lot numbers for which there is only one record in the table.
Lot numbers for which there are multiple records, but the Product description is the same for all of them
Lot numbers for which there are multiple records, and the product descriptions are not all the same.
I need to return only #3, with a separate record for each instance of that Lot Number and product description.
Any help would be greatly appreciated.
Thanks Juan for the sample data. Using this example, I want to return the data contained in Id 2-8, but not 1, 9, 10, 11.
This wasn't easy because lot of time don't use access.
First select unique values using distinct.
Then count how many diferent product appear on each lotnumber using group by
Last join both result and show only the lots with more than one description where total >1
.
SELECT id, Product.lotnumber, Product.Product, total
FROM
Product Inner join
(
SELECT lotnumber, count(*) as total
FROM
(SELECT distinct lotnumber, product
FROM Product)
GROUP BY lotnumber
) SubT On Product.lotnumber = SubT.lotnumber
WHERE total > 1
ORDER BY id
As you can see :
lot 2 have two products (yy and zz)
lot 3 have thre products (aa, bb, cc)
I include my product table:
Sorry for spanish. Field types are Autonumeric, Short Text, and Number