Retrieve all sales for customer - sql-server

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

Related

Select columns from several tables with count

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(*)

T-SQL max sales date and price on that sales

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

my query doesn't work as expected

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
)

SQL Group, get First purchase, Last Purchase and last employee associated with last purchase

In my DB I have Customers, who make Purchases, and those purchases are then associated with an employee who assisted with that purchase. I have written a query below that will provide me with a list of customers with how many total purchases they have made, their first purchase and the last purchase. I also want the employee name associated with the last purchase?
Customer
-cstId
-cstName
Purchase
-cstId
-soldDate
-empId
Employee
-FirstName
-LastName
-empId
SELECT customer.cstName, MAX(purchase.soldDate) AS [Last Purchase], MIN(purchase.soldDate) AS [First Purhcase], COUNT(invTruck.invId)
AS [Total Purchases]
FROM customer INNER JOIN
purchase ON customer.cstId = purchase.cstId
INNER JOIN
employee ON purchase.empId = employee.empId
GROUP BY customer.cstName
Can you use a stored procedure? I usually fall back to memory tables for situations like this.
Declare #tblCust TABLE (
cstid int null,
cstName varchar(50) null,
lastpurchase datetime null,
firstpurchase datetime null,
empid varchar(50) null
)
Insert into #tblCust(cstid, cstname, lastpurchase, firstpurchase)
SELECT purchase.cstid, customer.cstName, MAX(purchase.soldDate) AS [Last Purchase],
MIN(purchase.soldDate) AS [First Purhcase]
FROM customer INNER JOIN
purchase ON customer.cstId = purchase.cstId
GROUP BY purchase.cstId, customer.cstName
Update t set EmpId = p.EmpId
From #tblCust t
INNER JOIN Purchase p ON t.cstId = p.cstid and t.LastPurchase = p.soldDate
You now have the employee id on a temp table that you can return your data from, or join to any other tables you may need.
I'm assuming you have some primary key on purchase table. I named it "purchaseID":
SELECT customer.cstName,
MAX(purchase.soldDate) AS [Last Purchase],
MIN(purchase.soldDate) AS [First Purhcase],
COUNT(invTruck.invId) AS [Total Purchases],
LastPurchase.empID AS [Last Purchase Employee]
FROM customer INNER JOIN
purchase ON customer.cstId = purchase.cstId
INNER JOIN
employee ON purchase.empId = employee.empId
CROSS APPLY (
SELECT TOP 1 *
FROM purchase px
WHERE px.purchaseID = purchase.purchaseID
ORDER BY px.soldDate DESC) AS LastPurchase
GROUP BY customer.cstName,
LastPurchase.empID
What the CROSS APPLY does is runs the enclosed select statement on every record, utilizing the WHERE criteria also inside. It behaves similarly to an INNER JOIN relative to an OUTER APPLY which behaves similarly a LEFT JOIN.
you could use APPLY: http://msdn.microsoft.com/library/ms175156(v=sql.105).aspx
use cross apply to get the list of purchases and the respective employee, with TOP 1 and sort by soldDate desc
example:
CROSS APPLY (
select top 1 p.empId
from purchase p
where p.cstId = customer.cstId
order by soldDate desc
) o (emp)
and add o.emp to your select
i'm not 100% sure that the syntax is 100% perfect but the idea is there :P
You can just extend it with a simple SCALAR SUBQUERY
SELECT
customer.cstName,
MAX(purchase.soldDate) AS [Last Purchase],
MIN(purchase.soldDate) AS [First Purhcase],
COUNT(invTruck.invId) AS [Total Purchases],
(SELECT TOP(1) e.lastname
FROM purchase p
INNER JOIN employee e ON p.empId = e.empId
WHERE customer.cstId = p.cstId
ORDER BY p.soldDate DESC) lastPurchaseEmployee
FROM customer
INNER JOIN purchase
ON customer.cstId = purchase.cstId
INNER JOIN employee
ON purchase.empId = employee.empId
GROUP BY
customer.cstId, customer.cstName

SQL Complex Select - Trouble forming query

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

Resources