I have three tables, Customers, Sales and Products.
Sales links a CustomerID with a ProductID and has a SalesPrice.
select Products.Category, AVG(SalePrice) from Sales
inner join Products on Products.ProductID = Sales.ProductID
group by Products.Category
This lets me see the average price for all sales by category. However, I only want to include customers that have more than 3 sales records or more in the DB.
I am not sure the best way, or any way, to go about this. Ideas?
You haven't mentioned the customer data anywhere so I'll assume it's in the Sales table
You need to filter and restrict the Sales table first to the customers with more the 3 sales, then join to get product category and get the average across categories
select
Products.Category, AVG(SalePrice)
from
(SELECT ProductID, SalePrice FROM Sales GROUP BY CustomerID HAVING COUNT(*) > 3) S
inner join
Products on Products.ProductID = S.ProductID
group by
Products.Category
I'd try the following:
select Products.Category, AVG(SalePrice) from Sales s
inner join Products on Products.ProductID = s.ProductID
where
(Select Count(*) From Sales Where CustomerID = s.CustomerID) > 3
group by Products.Category
I'd create a pseudo-table of "big customer IDs" with a select, and then join it to your query to limit the results:
SELECT Products.Category, AVG(SalePrice) FROM Sales
INNER JOIN Products ON Products.ProductID = Sales.ProductID
INNER JOIN (
SELECT CustomerID FROM Sales WHERE COUNT(CustomerID) >= 3 GROUP BY CustomerID
) BigCustomer ON Sales.CustomerID = BigCustomer.CustomerID
GROUP BY Products.Category
Too lazy to test this out though, so let me know if it works ;o)
Another way
;WITH FilteredSales AS
(
SELECT Products.Category, Sales.SalesPrice, COUNT(Sales.CustomerId) OVER(PARTITION BY Sales.CustomerId) AS SaleCount
FROM Sales
INNER JOIN Products ON Products.ProductID = Sales.ProductID
)
select Category, AVG(SalePrice)
from FilteredSales
WHERE SaleCount > 3
group by Category
Related
I have 3 tables in SQL Server:
Sales (customerId)
Customer (customerId, personId)
Person (personId, firstName, lastName)
and I need to return the top 10 customers.
I used this query:
SELECT TOP 10
CustomerID, COUNT(CustomerID)
FROM
Sales
GROUP BY
(CustomerID)
ORDER BY
COUNT(CustomerID) DESC
The query currently returns only the customerId and count, but I also need to return the firstName and lastName of these customers from the Person table.
I know I need to reach the firstName and lastName by correlating between Sales.customerId and Customer.customerId, and from Customer.personId to get the Person.personId.
My question is whether I need to use an inner join or union, and how to use either of them to get the firstName and lastName of these customers
Union is mostly used for disjoint sets. To achieve your target, u can go with inner-join.
If you want to use joins, then here is the query which works similarly to your requirement.
SELECT TOP 10 S.CustomerID, P.FirstName,P.LastName, count(*)
FROM Sales S
INNER JOIN Customer C on S.CustomerId=C.CustomerId
INNER JOIN Person P on C.PersonId = P.PersonId
GROUP BY (S.CustomerID, P.FirstName,P.LastName)
ORDER BY count(*) DESC
You need use inner join like this :
SELECT TOP 10 S.CustomerID
, P.FirstName
, P.LastName
, COUNT (1) AS CountOfCustomer -- this is equal count(*)
FROM Sales S
INNER JOIN Customer C ON S.CustomerId = C.CustomerId
INNER JOIN Person P ON C.PersonId = P.PersonId
GROUP BY S.CustomerID, P.FirstName, P.LastName
ORDER BY 4 DESC; -- this is equal order by count(*)
I'm working with the northwind database and my exercise is:
Which suppliers offer two products in the same category? Show company name, category and the both product names
My code:
SELECT DISTINCT
c.CategoryID, s.CompanyName, p1.ProductName, p2.ProductName
FROM
Suppliers s
INNER JOIN
Products p1 ON s.SupplierID = p1.SupplierID
INNER JOIN
Products p2 ON p1.CategoryID = p2.CategoryID
AND p1.ProductID <> p2.ProductID
INNER JOIN
Categories c ON p2.CategoryID = c.CategoryID
GROUP BY
c.CategoryID,s.CompanyName, p1.ProductName, p2.ProductName`
How can I filter that with COUNT() I tried to do it with HAVING but I failed.
I'll appreciate some help, which bringing me back on the right way.
Building on Gordon's answer the code below will get all the data you need. If you absolutely have to have both products in the same row, you can use pivot:
select s.CompanyName
,p.ProductName
from Suppliers s
-- This join filters your Suppliers table to only those with two Products in the same Category
inner join (select SupplierID
,CategoryID
from Products
group by SupplierID
,CategoryID
having count(1) = 2
) pc
on(s.SupplierID = pc.SupplierID)
-- This join returns the two products in the Category returned in the join above.
inner join Products p
on(s.SupplierID = p.SupplierID
and pc.CategoryID = p.CategoryID
)
You can get the list of suppliers/categories with exactly two products using a query like this:
select supplierId, categoryId
from products
group by supplierId, categoryId
having count(*) = 2;
Then, write a query to show the supplier and products names, and use the above to filter the results from that query. You can use either exists or an additional join.
I have a sales table and products table. I'd like to retrieve the last sales and the product price of the last sales. Is there a query that can do this in a simple way:
Select Max(s.SalesDate), p.ProductName, Max(s.Price)
From Sales s
inner join products p
group by p.ProductName
This doesn't work because max(price) is not from the last sale
select * from
(
Select s.SalesDat, p.ProductName, Maxs.Price
, row_number() over (partition by p.ProductName order by s.SalesDat desc) as rn
From Sales s
inner join products p
) tt
where tt.rn = 1
clearly you are missing a join condition
I'm trying to get list of customers and then group sales per customer, the code below works, but not how I want it to.
I'm really after each customer to display once then all sales per customer.
SELECT i.item, i.Qty, c.NAME, c.address, s.OrderNo, s.OrderDate
FROM CUSTOMERS c
LEFT JOIN Sales s
ON c.name = s.cust
LEFT JOIN Items i
on i.OrderNo = s.OrderNo
WHERE s.Cust IS not NULL
--SubQuery the summed value by customer from the sales table then join to that.
SELECT i.item, i.Qty, c.NAME, c.address, s.OrderNo, s.OrderDate, s.SUM_CUSTOMER_SALES_VALUE
FROM CUSTOMERS c
LEFT JOIN ( SELECT Cust, SUM(CUSTOMER_SALES_VALUE) AS SUM_CUSTOMER_SALES_VALUE FROM Sales GROUP BY Cust ) s
ON c.name = s.cust
LEFT JOIN Items i
on i.OrderNo = s.OrderNo
WHERE s.Cust IS not NULL
SELECT Product.ProductName
,SUM(Purchase.Value) AS TotalPurchase
,SUM(Sales.Value) AS TotalSales
,((TotalPurchase) - (TotalSales)) AS ProductAvailability
FROM Product
INNER JOIN Purchase ON Product.ProductID = Purchase.ProductID
INNER JOIN Sales ON Product.ProductID = Sales.ProductID
GROUP BY Product.ProductName
I have 3 Table Product - Sales - Purchase
and i want Show product name total sales each product ,total purchase of each
product And how many of those product still unsold
SELECT Product.ProductName
,SUM(Purchase.Value) AS TotalPurchase
,ISNULL(SUM(Sales.Value),0) AS TotalSales
,(SUM(Purchase.Value) - ISNULL(SUM(Sales.Value),0)) AS ProductAvailability
FROM Product
LEFT JOIN Purchase ON Product.ProductID = Purchase.ProductID
LEFT JOIN Sales ON Product.ProductID = Sales.ProductID
GROUP BY Product.ProductName
Since you also want to show the unsold products , there will be no data for them products in the sales table, hence you need a LEFT JOIN here not an INNER JOIN.
Also the columns TotalPurchase and TotalSales are available to be called in the query they are being calculated , hence use a sub-query to manipulate these columns or use the expression itself.
After 5 Hours OF playing With Query I FOUND THE ANSWER
SELECT PN.ProductName,TotalPurchase ,TotalSales,TotalPurchase-TotalSales AS ProductAvailability
FROM
((SELECT SUM(Purchase.Value) AS TotalPurchase,Purchase.ProductID FROM Purchase GROUP BY Purchase.ProductID ) AS TP
INNER JOIN
(SELECT SUM(Sales.Value) AS TotalSales,Sales.ProductID FROM Sales GROUP BY Sales.ProductID ) AS TS
ON tp.ProductID=TS.ProductID
INNER JOIN
(SELECT Product.ProductName,Product.ProductID FROM Product GROUP BY Product.ProductName,ProductID) AS PN ON PN.ProductID=TS.ProductID
)