Find the nth highest - sql

SELECT CONCAT(C.CUSTOMER_FNAME, ' ',C.CUSTOMER_LNAME) AS FullNAME, SUM(QTY* PRICE)AS TOTAL_SPENDINGS
FROM (SELECT DISTINCT TOP 2 TOTAL_SPENDINGS) RESULT
Customers$ C INNER JOIN Invoices$ Inv ON C.CUSTOMER_ID=Inv.CUSTOMER_ID
INNER JOIN InvDetails$ InvD ON Inv.INVOICE_ID=InvD.INVOICE_ID
INNER JOIN Products$ P ON P.PRODUCT_ID=InvD.PRODUCT_ID
GROUP BY C.CUSTOMER_FNAME,C.CUSTOMER_LNAME
ORDER BY TOTAL_SPENDINGS DESC
I am trying to prin the k-highest spending customers this is what i have done until now but i get
Incorrect syntax near 'Customers$'.

You are missing the join condition between the calculated table RESULT and the Customers table:
SELECT CONCAT(C.CUSTOMER_FNAME, ' ',C.CUSTOMER_LNAME) AS FullNAME, SUM(QTY* PRICE)AS TOTAL_SPENDINGS
FROM (SELECT DISTINCT TOP 2 TOTAL_SPENDINGS) RESULT
<missing INNER / LEFT join here>
Customers$ C <missing ON here> INNER JOIN Invoices$ Inv ON C.CUSTOMER_ID=Inv.CUSTOMER_ID
INNER JOIN InvDetails$ InvD ON Inv.INVOICE_ID=InvD.INVOICE_ID
INNER JOIN Products$ P ON P.PRODUCT_ID=InvD.PRODUCT_ID
GROUP BY C.CUSTOMER_FNAME,C.CUSTOMER_LNAME
ORDER BY TOTAL_SPENDINGS DESC

Related

Volume of store sql

i want the top 10 stores with the highest volume(percentage) of sales and the 5 with the lowest volume(percentage) of sales in a single report. Here's what i have done until now
SELECT TOP 10 Stores.Store_ID,Suppliers$.NAME,SUM(Store.QTY*Product.PRICE) AS StoreSales
FROM Stores
INNER JOIN Invoices$ ON Stores.store_ID=Invoices.Store_ID
INNER JOIN InvDetails ON Invoices.INVOICE_ID=InvDetails.INVOICE_ID
INNER JOIN Products ON Products.PRODUCT_ID=InvDetails.PRODUCT_ID
GROUP BY Stores.Store_ID,Stores.NAME
ORDER BY StoresSales DESC
select TOP 10 ...
from ...
group by ...
order by StoresSales DESC
union
select TOP 5 ...
from ...
group by ...
order by StoresSales ASC
You can do this with a CTE by dividing the query in two, the first part extracts the highest and the second part the lowest
With c as(
SELECT TOP 10 Stores.Store_ID,Suppliers$.NAME,SUM(Store.QTY*Product.PRICE) AS StoreSales
,cat = 'Max'
FROM Stores
INNER JOIN Invoices$ ON Stores.store_ID=Invoices.Store_ID
INNER JOIN InvDetails ON Invoices.INVOICE_ID=InvDetails.INVOICE_ID
INNER JOIN Products ON Products.PRODUCT_ID=InvDetails.PRODUCT_ID
GROUP BY Stores.Store_ID,Stores.NAME
ORDER BY StoresSales DESC
),
d as (
SELECT TOP 5 Stores.Store_ID,Suppliers$.NAME,SUM(Store.QTY*Product.PRICE) AS StoreSales
,cat = 'Min'
FROM Stores
INNER JOIN Invoices$ ON Stores.store_ID=Invoices.Store_ID
INNER JOIN InvDetails ON Invoices.INVOICE_ID=InvDetails.INVOICE_ID
INNER JOIN Products ON Products.PRODUCT_ID=InvDetails.PRODUCT_ID
GROUP BY Stores.Store_ID,Stores.NAME
ORDER BY StoresSales asc
)
Select *
From c
Union all
Select *
From d
You can use ROW_NUMBER() :
SELECT Stores.Store_ID, Suppliers$.NAME, SUM(Store.QTY*Product.PRICE) AS StoreSales,
ROW_NUMBER() OVER (PARTITION BY Stores.Store_ID, Suppliers$.NAME ORDER BY SUM(Store.QTY*Product.PRICE) DESC) AS MAX_SEQ,
ROW_NUMBER() OVER (PARTITION BY Stores.Store_ID, Suppliers$.NAME ORDER BY SUM(Store.QTY*Product.PRICE)) AS MIN_SEQ
FROM Stores INNER JOIN
Invoices$
ON Stores.store_ID = Invoices.Store_ID INNER JOIN
InvDetails
ON Invoices.INVOICE_ID = InvDetails.INVOICE_ID INNER JOIN
Products
ON Products.PRODUCT_ID = InvDetails.PRODUCT_ID
GROUP BY Stores.Store_ID, Suppliers$.NAME;
By using this, you can filter out :
SELECT t.*
FROM ( <query here>
) t
WHERE (t.MAX_SEQ <= 10 OR MIN_SEQ <= 5);
You could union your query with basically the same query, but change it to top 5 and in ascending order:
SELECT TOP 10 Stores.Store_ID,Suppliers$.NAME,SUM(Store.QTY*Product.PRICE) AS
StoreSales
FROM Stores
INNER JOIN Invoices$ ON Stores.store_ID=Invoices.Store_ID
INNER JOIN InvDetails ON Invoices.INVOICE_ID=InvDetails.INVOICE_ID
INNER JOIN Products ON Products.PRODUCT_ID=InvDetails.PRODUCT_ID
GROUP BY Stores.Store_ID,Stores.NAME
ORDER BY StoresSales DESC
UNION
SELECT TOP 5 Stores.Store_ID,Suppliers$.NAME,SUM(Store.QTY*Product.PRICE) AS
StoreSales
FROM Stores
INNER JOIN Invoices$ ON Stores.store_ID=Invoices.Store_ID
INNER JOIN InvDetails ON Invoices.INVOICE_ID=InvDetails.INVOICE_ID
INNER JOIN Products ON Products.PRODUCT_ID=InvDetails.PRODUCT_ID
GROUP BY Stores.Store_ID,Stores.NAME
ORDER BY StoresSales ASC

Why does an incorrect syntax error near appears?

I get an error that Incorrect syntax near the keyword 'DESC'.
SELECT S.NAME, SUM([QTY] * [PRICE]) AS SALES
FROM Invoices$ Inv INNER JOIN InvDetails$ InvD ON
Inv.INVOICE_ID=InvD.INVOICE_ID
INNER JOIN Products$ P ON InvD.PRODUCT_ID=P.PRODUCT_ID
INNER JOIN Stores$ S ON S.STORE_ID=Inv.STORE_ID
GROUP BY SALES DESC
The expected result is to print all stores and their sales sorted by total sales(SALES) in desecding order
You mean to GROUP BY S.NAME, not SALES.
Also GROUP BY does not care about order, so move DESC to after the ORDER BY. You can't combine GROUP BY and ORDER BY into a single clause.
GROUP BY S.NAME
ORDER BY SALES DESC;
You query should look like this:
SELECT S.NAME, SUM([QTY] * [PRICE]) AS SALES
FROM Invoices$ Inv INNER JOIN
InvDetails$ InvD
ON Inv.INVOICE_ID = InvD.INVOICE_ID INNER JOIN
Products$ P
ON InvD.PRODUCT_ID = P.PRODUCT_ID INNER JOIN
Stores$ S
ON S.STORE_ID = Inv.STORE_ID
GROUP BY S.NAME
ORDER BY SALES DESC;
DESC is supported as a keyword for GROUP BY in MySQL (although I think that usage has been deprecated in v8). However, that is an extension not used by other databases.
In any case, the GROUP BY should contain all the non-aggregated keys in the SELECT. That would be S.NAME, not SALES.
you need to name column add in group by
SELECT S.NAME, SUM([QTY] * [PRICE]) AS SALES
FROM Invoices$ Inv INNER JOIN InvDetails$ InvD ON
Inv.INVOICE_ID=InvD.INVOICE_ID
INNER JOIN Products$ P ON InvD.PRODUCT_ID=P.PRODUCT_ID
INNER JOIN Stores$ S ON S.STORE_ID=Inv.STORE_ID
GROUP BY S.NAME order by SALES desc

Select a name in sql

I selecting the category name from a category table using the below query
select Category.Name
from Product
inner join ProductCategory on ProductCategory.PID=Product.PID
inner join ProductMaterial on ProductMaterial.PID=Product.PID
left join Category on Category.NodeId=ProductCategory.CID
where PID in('2233','4432','5665','1252')
group by ProductCategory.CID, ProductMaterial.MID,Category.DanishName
the query is working the result of this query is
Electronics
Electronics
Electronics
Home and Garden
I want only select most number of category name, here I need only Electronics.How to get this.Thanks in advance for help...>>
Try this:
MySQL
SELECT A.name, COUNT(A.name) nameCnt
FROM (SELECT C.Name
FROM Product P
INNER JOIN ProductCategory PC ON PC.PID=P.PID
INNER JOIN ProductMaterial PM ON PM.PID=P.PID
INNER JOIN Category C ON C.NodeId=PC.CID
WHERE PID IN('2233','4432','5665','1252')
GROUP BY PC.CID, PM.MID, C.DanishName
) AS A
GROUP BY A.name
ORDER BY nameCnt DESC LIMIT 1;
SQL Server
SELECT TOP 1 A.name, COUNT(A.name) nameCnt
FROM (SELECT C.Name
FROM Product P
INNER JOIN ProductCategory PC ON PC.PID=P.PID
INNER JOIN ProductMaterial PM ON PM.PID=P.PID
INNER JOIN Category C ON C.NodeId=PC.CID
WHERE PID IN('2233','4432','5665','1252')
GROUP BY PC.CID, PM.MID, C.DanishName
) AS A
GROUP BY A.name
ORDER BY nameCnt DESC;

SQL GroupBy & InnerJoin

SELECT
C.SOId, Ser.TotalService, S.TotalSales
FROM
salesorder C
INNER JOIN (SELECT SOId,SUM(charge) as TotalService FROM sales_serviceline GROUP BY SOId) Ser
ON C.SOId = Ser.SOId
INNER JOIN (SELECT SOId,SUM(PriceEach*qty) as TotalSales FROM salesline GROUP BY SOId) S
ON C.SOId = S.SOId
Explanation :
One SalesOrder has many salesline's
One SalesOrder has many salesline services's
so if a salesorder has saleslins & salesline_service then the above query successfully retrives the total amount of that salesorder but if there's only salineline or only salesline service that sales order is not retried how to change this query to get all the results ?
I think you are looking for a LEFT JOIN. If there is no rows in Ser or S then the LEFT JOIN will make TotalService or TotalSales NULL
SELECT
C.SOId, Ser.TotalService, S.TotalSales
FROM
salesorder C
LEFT JOIN (SELECT SOId,SUM(charge) as TotalService FROM sales_serviceline GROUP BY SOId) Ser
ON C.SOId = Ser.SOId
LEFT JOIN (SELECT SOId,SUM(PriceEach*qty) as TotalSales FROM salesline GROUP BY SOId) S
ON C.SOId = S.SOId
If you do not want to have them as NULL. Then you can quit easy use COALESCE(). Like this:
SELECT
C.SOId,
COALESCE(Ser.TotalService,0) AS TotalService,
COALESCE(S.TotalSales,0) AS TotalSales
FROM
salesorder C
LEFT JOIN (SELECT SOId,SUM(charge) as TotalService FROM sales_serviceline GROUP BY SOId) Ser
ON C.SOId = Ser.SOId
LEFT JOIN (SELECT SOId,SUM(PriceEach*qty) as TotalSales FROM salesline GROUP BY SOId) S
ON C.SOId = S.SOId

INNER JOIN Distinct ID

I have the following code:
FROM CTE_Order cte
INNER JOIN tblOrders o
ON cte.OrderId = o.Id
INNER JOIN tblOrderUnits ou
ON o.id = ou.OrderId
INNER JOIN tblOrderServiceUnits osu
ON ou.VMSUnitID = osu.UnitId
When I join the ou I get 2 of the same unit Id's. This make the Inner Join tblOrderServiceUnits return 4 rows with 2 being duplicates. I need it to only return the 2 rows the are different. How do I use a distinct to Inner Join only distinct ou.id?
Sorry for the bad explanation but basically I am jsut trying to see how an INNER JOIN with a distinct subquery would work, If someone could give me an example of that I could figure it out from there.
INNER JOIN (SELECT DISTINCT * FROM X) Alias
ON Alias.ID = Primary.ID
For your example:
INNER JOIN (SELECT DISTINCT VMSUnitID, OrderId FROM tblOrderUnits) ou
ON o.id = ou.OrderId