Total sum value out of Group By - sql

I have a drugstore chain database. In the script below I'm trying to print out
store
category
sales of particular category in the particular store
total sales of the particular category in all the stores
My code:
SELECT
s.store_name AS [Drug Store],
g.group_name AS [Category],
SUM(f.quantity) AS [Sales pcs.]
-- (SELECT SUM(quantity) AS [Total sales] GROUP BY g.group_name)
FROM
[dbo].[fct_cheque] AS f
INNER JOIN
[dim_stores] AS s ON s.store_id = f.store_id
INNER JOIN
dim_goods AS g ON g.good_id = f.good_id
WHERE
date_id BETWEEN '20170601' AND '20170630'
GROUP BY
s.store_name, g.group_name
How to handle the last one?

You may use SUM() as an analytic function, for the second sum which is commented out in your question:
SELECT s.store_name AS [Drug Store],
g.group_name AS [Category],
SUM(f.quantity) AS [Sales pcs.],
SUM(SUM(f.quantity)) OVER (PARTITION BY g.group_name) AS [Total sales]
FROM [dbo].[fct_cheque] AS f
INNER JOIN [dim_stores] AS s ON s.store_id = f.store_id
INNER JOIN dim_goods AS g ON g.good_id = f.good_id
WHERE date_id BETWEEN '20170601' AND '20170630'
GROUP BY s.store_name, g.group_name;

Related

SQL DML how to combine value from other row after using count, sql server

this is my code:
select CustomerName, count(td.bikeid) as [Total Transactions], sum(quantity) as [Total Bikes Bought],
replace(customerphone, '0', '+62') as [Customer Phone]
from MsCustomer mc join TransactionHeader th
on mc.CustomerID = th.CustomerID join TransactionDetail td
on th.TransactionID = td.TransactionID join MsBike mb
on td.BikeID = mb.BikeID
group by td.BikeID, td.TransactionID, CustomerName, Quantity, CustomerPhone
having sum(Quantity) > 5 and count(th.transactionid) between 2 and 5
and the result is this
How can I make it so that the total transactions and bikes bought of the same customername got summed up, for example of the result I want:
(cendana, 2, 16, +6283859786138)
Your GROUP BY clause seems the culprit here. Usually, all the ungrouped columns from SELECT list will go into GROUP BY clause but you have multiple columns in GROUP BY clause without using them in SELECT list. Using those unnecessary columns in GROUP BY clasue is causing this issue. Just get rid of those columns, And you probably get your result -
SELECT CustomerName,
COUNT(td.bikeid) AS [Total Transactions],
SUM(quantity) AS [Total Bikes Bought],
REPLACE(customerphone, '0', '+62') AS [Customer Phone]
FROM MsCustomer mc
JOIN TransactionHeader th ON mc.CustomerID = th.CustomerID
JOIN TransactionDetail td ON th.TransactionID = td.TransactionID
JOIN MsBike mb ON td.BikeID = mb.BikeID
GROUP BY CustomerName, CustomerPhone
HAVING SUM(Quantity) > 5
AND COUNT(th.transactionid) BETWEEN 2 AND 5;

MS SQL - Grouping orders by month and showing the total yearly amount of orders for that year

I need to create a query that will join data from two tables:
[Orders]
[People]
and give the following output:
SalespersonID
FullName
Order Month
Monthly amount of orders
Yearly amount of orders
The trick here is with the Yearly amount of orders. While the monthly amount of orders should be broken down by the month, the yearly amount should be the same for each given month & salesperson.
The first thing that came to my mind is to use OVER (PARTITION BY <column x> ORDER BY <column y>).
So, I came up with this query:
SELECT
ORD.SalespersonPersonID,
PEO.FullName,
[Order Month] = MONTH(ORD.OrderDate),
[Monthly Amount of Orders] = COUNT(ORD.OrderID),
[Yearly Amount of Orders] = COUNT(ORD.OrderID) OVER (PARTITION BY ORD.SalespersonPersonID ORDER BY MONTH(ORD.OrderDate))
FROM [Sales].[Orders] ORD LEFT JOIN [Application].[People] PEO
ON ORD.SalespersonPersonID = PEO.PersonID
WHERE YEAR(ORD.OrderDate) = '2016'
GROUP BY ORD.SalespersonPersonID, PEO.FullName, MONTH(ORD.OrderDate), ORD.OrderID
ORDER BY PEO.FullName
The problem is because I have to mention ORD.OrderID in the GROUP BY it breaks the monthly aggregation.
I came with a different approach and solved this (Using a CTE):
WITH table1 AS
(
SELECT
SalespersonPersonID,
[Yearly Amount of Orders] = COUNT(OrderID)
FROM [Sales].[Orders]
WHERE YEAR(OrderDate) = '2016'
GROUP BY SalespersonPersonID
)
SELECT
ORD.SalespersonPersonID,
PEO.FullName,
[Order Month] = MONTH(ORD.OrderDate),
[Monthly Amount of Orders] = COUNT(ORD.OrderID),
T1.[Yearly Amount of Orders]
FROM [Sales].[Orders] ORD
LEFT JOIN [Application].[People] PEO
ON ORD.SalespersonPersonID = PEO.PersonID
LEFT JOIN table1 AS T1
ON ORD.SalespersonPersonID = T1.SalespersonPersonID
WHERE YEAR(ORD.OrderDate) = '2016'
GROUP BY ORD.SalespersonPersonID, PEO.FullName, MONTH(ORD.OrderDate), T1.[Yearly Amount of Orders]
ORDER BY PEO.FullName
I am still wondering how it is possible to run this using OVER (PARTITION BY <column x> ORDER BY <column y>). Feels like it is the more elegant way to solve this.
Thanks,
Michael
No need for a cte or the-like. Starting from your original group by query, you would would do:
SUM(COUNT(ORD.OrderID)) OVER (PARTITION BY ORD.SalespersonPersonID
as [Yearly Amount of Orders]
Conceptually, the window function operates on the resultset after aggregation has been performed. You can then access the monthly count of each row, and sum the whole year for the sales person.
Notes:
you want the same value on all rows of the same person, so do not use an order by clause in the over() clause
I doubt that OrderID can ever be null; if so, then use COUNT(*) instead of COUNT(ORD.OrderID). It is more efficient since the database does not need to check for nullity
I think you want:
SELECT
ORD.SalespersonPersonID,
PEO.FullName,
[Order Month] = MONTH(ORD.OrderDate),
[Monthly Amount of Orders] = COUNT(ORD.OrderID),
[Yearly Amount of Orders] = SUM(COUNT(ORD.OrderID)) OVER (PARTITION BY ORD.SalespersonPersonID)
FROM [Sales].[Orders] ORD LEFT JOIN
[Application].[People] PEO
ON ORD.SalespersonPersonID = PEO.PersonID
WHERE YEAR(ORD.OrderDate) = '2016'
GROUP BY ORD.SalespersonPersonID, PEO.FullName, MONTH(ORD.OrderDate)
ORDER BY PEO.FullName;
The only change is to the yearly amount of orders.

Find employee who made highest sales to the customer who made most purchases

I'm having trouble with this question in my Database homework And need to answer this question:
Which employee has the highest sales to the customer who has made the most purchases?
And these are my database tables
And these are my attempts to write this query
--select Customers.Firstname,Products.Name,Sales.Quantity from Customers
--inner join Sales
--on Customers.CustomerId=Sales.CustomerId
--inner join Products
--on Sales.productId=Products.ProductId
--where Products.Name like 'Mobile'
--Select Customers.CustomerId,max(COUNT(Customers.CustomerId)) As Customecount,Emploees.EmploeeId,max(COUNT(Emploees.EmploeeId))as EmploeeeCount from Emploees
--inner join Sales
--on Emploees.EmploeeId=Sales.EmploeeId
--inner join Customers
--on Customers.CustomerId=Sales.CustomerId
--group by Customers.CustomerId,Emploees.EmploeeId ,Count(Sales.productId)as productCount,Count(Emploees.EmploeeId)as emploeeCount,Count(Customers.CustomerId)as customerCount
select * from
(select Distinct Customers.CustomerId,Sales.productId,COUNT(Sales.productId)as CountProduct from Customers
inner join Sales
on Customers.CustomerId=Sales.CustomerId
inner join Emploees
on Emploees.EmploeeId=Sales.EmploeeId
group by Sales.productId,Emploees.EmploeeId,Customers.CustomerId,Sales.productId) as Result
--gr
But these don't work
Please, help me to write this Query.
Try to solve the problem step by step. Find the customer id with most orders by total:
SELECT TOP 1 sales.customerid
FROM sales
JOIN products ON sales.productid = products.productid
GROUP BY sales.customerid
ORDER BY SUM(sales.quantity * products.price) DESC
Next step is to find the employee with most sales by count to that customer (changing it to by total is trivial):
SELECT TOP 1 sales.salespersonid
FROM sales
WHERE sales.customerid = (
SELECT TOP 1 sales.customerid
FROM sales
JOIN products ON sales.productid = products.productid
GROUP BY sales.customerid
ORDER BY SUM(sales.quantity * products.price)
)
GROUP BY sales.salespersonid
ORDER BY COUNT(sales.salesid) DESC
Finally select the employee record:
SELECT *
FROM employee
WHERE employeeid = (
SELECT TOP 1 sales.salespersonid
FROM sales
WHERE sales.customerid = (
SELECT TOP 1 sales.customerid
FROM sales
JOIN products ON sales.productid = products.productid
GROUP BY sales.customerid
ORDER BY SUM(sales.quantity * products.price)
)
GROUP BY sales.salespersonid
ORDER BY COUNT(sales.salesid) DESC
)
Maybe something like this....
First get the customer with most purchases and then find all employees who have sold to that customer and return the top 1 employee with the most sales.
SELECT TOP (1)
e.EmploeeId
, SUM(s.quantity * p.Price) TotalSales
FROM Emploees e
inner join Sales s ON e.EmploeeId = s.EmploeeId
inner join Product p ON s.productId = s.productId
WHERE s.CustomerId = (
-- Get the customer with most purchases
SELECT TOP (1) x.CustomerId
FROM ( SELECT
c.CustomerId
, SUM(s.quantity * p.Price) TotalSales
FROM Customers c
inner join Sales s ON c.CustomerId = s.CustomerId
inner join Product p ON s.productId = o.productId
GROUP BY c.CustomerId
) x
ORDER BY TotalSales DESC
)
GROUP BY e.EmploeeId
ORDER BY TotalSales DESC
To find Most Sales and Purchases by count (Number of sales/Purchases) following query will do the trick:
SELECT TOP (1)
e.EmploeeId
, COUNT(*) TotalSales
FROM Emploees e
inner join Sales s ON e.EmploeeId = s.EmploeeId
WHERE s.CustomerId = (
SELECT TOP (1) x.CustomerId
FROM ( SELECT
c.CustomerId
, COUNT(*) TotalSales
FROM Customers c
inner join Sales s ON c.CustomerId = s.CustomerId
GROUP BY c.CustomerId
) x
ORDER BY TotalSales DESC
)
GROUP BY e.EmploeeId
ORDER BY TotalSales DESC
In one of the comments you said that "most sales" mean more sale quantity. This answer takes this criteria into consideration.
SELECT TOP (1) SalesPersonID,
(FirstName + ' ' + MiddleName + ' ' + LastName) AS EmployeeName
FROM Sales S
JOIN Employees E ON S.SalesPersonID = E.EmployeeID
WHERE CustomerID =
(
-- Sub-query that returnes CustomerID with most quantities bought
SELECT TOP (1) CustomerID
FROM Sales
GROUP BY CustomerID
ORDER BY SUM(Quantity) DESC
)
GROUP BY SalesPersonID,
(FirstName + ' ' + MiddleName + ' ' + LastName)
ORDER BY SUM(Quantity)

I am having trouble finding the average sales of all shops

I can't seem to find a solution on how to receive the sales of the shops that are bigger than the average of all shops.
I have already tried some ways and managed to get the average sales of each shop. I have then tried to get the shops that have sales bigger than the average of all shops but have failed.
SELECT SALES, (SELECT AVG(AVERSALES * SALES)) AS AVGSALES FROM
(
SELECT
Shops.NAME,
SUM(InvDet.QTY * Products.PRICE ) AS SALES,
AVG(InvDet.QTY * Products.PRICE) AS AVERSALES
FROM
Invoices
INNER JOIN InvDet ON Invoices.INV_ID = InvDet.INV_ID
INNER JOIN Products ON InvDet.PR_ID = Products.PR_ID
INNER JOIN Shops ON Shops.S_ID=Invoices.S_ID
WHERE
Invoices.INVOICE_DATE BETWEEN '2013-06-24' AND '2013-06-30'
GROUP BY Shops.NAME
)AS SALES_TABLE
GROUP BY SALES
HAVING SALES > (SELECT AVG(AVERSALES))
You have many ways to get what you are looking for.
One of them should be this:
select
s.name,
s.SALES
from (
select
s.name,
sum(i.QTY * p.PRICE) AS SALES
from Invoices i
join InvDet id ON i.INV_ID = id.INV_ID
join Products p ON id.PR_ID = p.PR_ID
join Shops s ON s.S_ID=i.S_ID
where i.INVOICE_DATE BETWEEN '2013-06-24' AND '2013-06-30'
group by s.name
) s
join (
select avg(i.QTY * p.PRICE) as average
from Invoices i
join InvDet id ON i.INV_ID = id.INV_ID
join Products p ON id.PR_ID = p.PR_ID
-- If you want to compare with the total average
-- remove this where part
where i.INVOICE_DATE BETWEEN '2013-06-24' AND '2013-06-30'
) a
on s.SALES>a.average
This other approach (for me clearer) must return the same:
declare #average float
select #average=avg(i.QTY * p.PRICE)
from Invoices i
join InvDet id ON i.INV_ID = id.INV_ID
join Products p ON id.PR_ID = p.PR_ID
-- If you want to compare with the total average
-- remove this where part
where i.INVOICE_DATE BETWEEN '2013-06-24' AND '2013-06-30'
select
s.name,
sum(i.QTY * p.PRICE) AS SALES
from Invoices i
join InvDet id ON i.INV_ID = id.INV_ID
join Products p ON id.PR_ID = p.PR_ID
join Shops s ON s.S_ID=i.S_ID
where i.INVOICE_DATE BETWEEN '2013-06-24' AND '2013-06-30'
group by s.name
having sum(i.QTY * p.PRICE)>#average
There are other choices (for example a common table expression would fit well here too). I think with these two is enough to solve your question. I hope they fit with what you need.
I am not sure about your requirement
SELECT SALES, (SELECT AVG(AVERSALES * SALES)) AS AVGSALES FROM
(
SELECT
Shops.NAME,
SUM(InvDet.QTY * Products.PRICE ) AS SALES,
AVG(InvDet.QTY * Products.PRICE) AS AVERSALES
FROM
Invoices
INNER JOIN InvDet ON Invoices.INV_ID = InvDet.INV_ID
INNER JOIN Products ON InvDet.PR_ID = Products.PR_ID
INNER JOIN Shops ON Shops.S_ID=Invoices.S_ID
WHERE
Invoices.INVOICE_DATE BETWEEN '2013-06-24' AND '2013-06-30'
GROUP BY Shops.NAME
)AS SALES_TABLE
GROUP BY SALES
HAVING SALES > AVERSALES

product which has sold the most inner join

I need to show the most popular selling item from the products table joining the sales table.
I need to display the most popular selling items.
Here's the code I've tried :
SELECT products.prod_id, products.prod_name, sales.quantity,
FROM products
INNER JOIN sales ON products.prod_id = sales.prod_id
Here are pics products and sales
products
sales
SELECT products.prod_id, products.prod_name, SUM(sales.quantity) as sales_total,
FROM products
INNER JOIN sales ON products.prod_id = sales.prod_id
GROUP BY products.prod_id, products.prod_name
ORDER BY sales_total DESC
SELECT products.prod_id, products.prod_name, sum(sales.quantity) as sales_total
FROM products
INNER JOIN sales ON products.prod_id = sales.prod_id
GROUP BY products.prod_id, products.prod_name
SELECT products.prod_id, products.prod_name, SUM(sales.quantity),
FROM products
INNER JOIN sales ON products.prod_id = sales.prod_id
GROUP BY prod_id
ORDER BY 3 DESC
LIMIT 25
You will want an index such as (prod_id, quantity) on sales.
SELECT b.prod_id, p.prod_name, b.Qty
FROM (
SELECT a.prod_id, a.Qty, MAX(a.Qty) OVER () AS MaxQty
FROM (
SELECT s.prod_id, SUM(s.quantity) AS Qty
FROM sales s
GROUP BY s.prod_id ) a ) b
INNER JOIN Products p ON p.prod_id = b.prod_id
WHERE b.Qty = b.MaxQty