filling one table column with if else statement in SQL - sql

I want to check if a product is one of TOP 10 product (from eye side of selling in Sales.SalesOrderDetails) make one column and set it to YES or NO
I have TOP 10 products of MAX selling like this:
SELECT TOP 10 p.Name , COUNT(*) 'Num of sell' FROM Sales.SalesOrderDetail SOD
inner join Production.Product p on SOD.ProductID = p.ProductID
GROUP BY p.Name
ORDER BY COUNT(*) DESC
now i want another table which is all of products and I want to somehow put a column with a if/else statement and put yes or no in there. like:
SELECT p.Name, #someVariable FROM Production.Product p
IF p.Name IN
(SELECT TOP 10 p.Name , COUNT(*) 'Num of sell' FROM Sales.SalesOrderDetail SOD
inner join Production.Product p on SOD.ProductID = p.ProductID
GROUP BY p.Name
ORDER BY COUNT(*) DESC)
#someVariable = 'YES'
ELSE #someVariable = 'NO'
any idea ?

You can do:
SELECT p.Name,
CASE WHEN X.ProductID IS NULL THEN 'NO' ELSE 'YES' END AS InTopTen
FROM Production.Product p
LEFT JOIN
(
SELECT TOP 10 ProductID FROM Sales.SalesOrderDetail
GROUP BY ProductID
ORDER BY COUNT(*) DESC
) X
ON X.ProductID = p.ProductID

Related

How to select top 300 for each orders total order item value

I want to view the top 300 items ordered by total net price, how do I do this please?
Using SSMS 2014
If I remove group by I get error: Column 'orderitems.orderid' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Please see workings below:
select top 300
orderitems.orderid, orders.traderid, orders.orderdate,
SUM(orderitems.nettprice) AS nettprice
from orderitems
INNER JOIN orders ON orders.tradertype = 'S' AND orders.id =
orderitems.orderid
where orderitems.ordertype = 'PO'
group by orderitems.orderid, orders.traderid, orders.orderdate,
orderitems.nettprice
order by orderitems.nettprice DESC
You need to order by the SUM value. You can either put that in the ORDER BY explicitly, or you can use the SELECT column name without a table reference (in other words the column alias you use in the SELECT)
I strongly recommend you use short table aliases to make your code more readable
select top 300
oi.orderid,
o.traderid,
o.orderdate,
SUM(oi.nettprice) AS nettprice
from orderitems AS oi
INNER JOIN orders AS o ON o.tradertype = 'S' AND o.id = oi.orderid
where oi.ordertype = 'PO'
group by
oi.orderid, o.traderid, o.orderdate
order by
nettprice DESC
-- alternatively
order by
SUM(oi.nettprice) DESC
Perhaps what you need here is a windowed SUM and then a TOP. The PARTITION BY clause is based on this comment:
SELECT TOP (300)
oi.orderid,
o.traderid,
o.orderdate,
SUM(oi.nettprice) OVER (PARTITION BY oi.itemnumber, oi.partid, oi.quantity) AS totalnettprice
FROM dbo.orderitems oi
INNER JOIN dbo.orders o ON o.id = oi.orderid
WHERE o.tradertype = 'S'
AND oi.ordertype = 'PO'
ORDER BY oi.totalnettprice DESC;
Very simple:
select top 300
itm.orderid,
ord.traderid,
ord.orderdate,
SUM(itm.nettprice) AS price
from orderitems itm
INNER JOIN orders ord ON
ord.tradertype = 'S' AND ord.id = itm.orderid
where itm.ordertype = 'PO'
group by
itm.orderid,
ord.traderid,
ord.orderdate
order by price DESC

Output of two different queries as one result in oracle

I have two different tables and I want to get these two different output in single result. Here I want to display the result of both queries in single report.
Query 1
Select name, sum(purchasqty)-sum (soldqty) as pending
from (select p.name, p.qty as purchasqty, s.qty as soldqty
from purchase p
left join sold s on p.id = s.id )
group by name;
Query 2
Select name, sum(qty) as damage
from purchase p
where con = 'c'
group by name
This will do
Select name, sum(purchasqty)-sum (soldqty) as pending, '' as damage
from (select p.name, p.qty as purchasqty, s.qty as soldqty
from purchase p
left join sold s on p.id = s.id )
group by name
union all
Select name, '' as pending, sum(qty) as damage
from purchase p
where con = 'c'
group by name
This is a little tricky because you seem to be aggregating at a level different from what you are joining on. I would recommend:
select p.name, (p.purchasqty - coalesce(ps.soldqty, 0) as pending ,
p.damage
from (select p.name, sum(qty) as purchase_qty,
sum(case when con = 'c' then qty else 0 end) as damage
from purchase p
group by p.name
) p left join
(select p.name, sum(s.qty) as soldqty
from purchase p join
sold s
on p.id = s.id
group by p.name
) ps
on ps.name = p.name;

Display Product Name and City where that product sold in largest quantity

I'm trying to get a query to display the product name and city where the product had the highest quantity sold. Here is the code I'm working with:
SELECT DISTINCT
(s.city),
MAX(t.quantity),
p.Name
FROM [DS715-Cameron-Erwin].dbo.Tb_Transactions AS t,
[DS715-Cameron-Erwin].dbo.Tb_Product AS p,
[DS715-Cameron-Erwin].dbo.Tb_Supplier AS s
WHERE p.prod_id = t.prod_id
AND s.Supp_ID = t.Supp_ID
GROUP BY t.Prod_ID,
p.name,
s.city
ORDER BY p.name, s.city
This is giving me the highest quantity sold for each product in each city.
Sample Data
From the screenshot there are multiple records for each product (Airplane, Auto, Boat...). I'm trying to get a single record for each product where ever the highest quantity was purchased.
So, the top record would only show for Airplane because the most orders were from there.
You want to use the ROW_NUMBER() OVER functionality to order by the quantity and then select the one with the biggest quantity over each product.
SELECT
city,
quantity,
name
FROM
(
SELECT S.city,
T.quantity,
P.name,
ROW_NUMBER() OVER
( PARTITION BY
P.name
ORDER BY t.Quantity DESC
) as RowNum
FROM
Tb_Transactions T
INNER JOIN
Tb_Product P
ON
P.prod_id = T.prod_id
INNER JOIN
Tb_Supplier S
ON
S.supp_id = T.supp_id
) a
WHERE
RowNum = 1
http://sqlfiddle.com/#!6/628458/5
For this, I would use a CTE (also I would use the explicit INNER JOIN syntax):
;With CTE
As
(
Select
s.city
, t.quantity
, p.Name
, Row_Number Over (Partition By P.Name, s.city Order By t.Quantity Desc) as RN
From [DS715-Cameron-Erwin].dbo.Tb_Transactions as t
Inner Join [DS715-Cameron-Erwin].dbo.Tb_Product as p
On p.prod_id = t.prod_id
Inner Join [DS715-Cameron-Erwin].dbo.Tb_Supplier as s
On s.Supp_ID = t.Supp_ID
)
Select
city
, quantity
, Name
From CTE
Where RN = 1

Selecting the Id of the item with a MAX value when doing a left join

Each product in the database can have many revisions. Some products might not have any revisions at all.
ProductRevision table has the following fields: Id, Version, SubmitDate
I am trying to figure out how I can select a field called LatestRevisionId based on the MAX SubmitDate and if not revision then the field will be null
SELECT p.Id, p.Name, p.Price
FROM Product p
LEFT OUTER JOIN ProductRevision pr ON p.Id = pr.ProductId
Do I have to do a sub select in my select? I really want to try and use HAVING but can't figure out how to do it with a left join.
I was trying to do the following as a sub select:
(SELECT Id
FROM ProductRevision
WHERE ProductId=p.Id
HAVING SubmitDate=MAX(SubmitDate)
) AS LatestVersionId
Please note that I am using SQL SERVER 2008
Here's one option using row_number:
SELECT *
FROM (
SELECT p.Id, p.Name, p.Price, pr.id as LatestRevisionId,
row_number() over (partition by p.Id order by pr.SubmitDate desc) rn
FROM Product p
LEFT OUTER JOIN ProductRevision pr PN p.Id = pr.ProductId
) t
WHERE rn = 1
This will select a single Product with the latest matching row from the ProductRevision table.
If you just prefer to use max, then you need to join the table back to itself again:
SELECT p.Id, p.Name, p.Price, pr.id as LatestRevisionId
FROM Product p
LEFT OUTER JOIN ProductRevision pr PN p.Id = pr.ProductId
LEFT OUTER JOIN (SELECT ProductId, MAX(SubmitDate) MaxSubmitDate
FROM ProductRevision
GROUP BY ProductId) mpr ON pr.ProductId = mpr.ProductId AND
pr.SubmitDate = mpr.MaxSubmitDate
This could perhaps return duplicates though if multiple revisions share the same date.
if you are using SQL Server 2012 and aboe, below code will give you desired result.
SELECT DISTINCT p.Id, p.Name, p.Price, FIRST_VALUE(pr.ID) OVER (PARTITION BY p.Id ORDER BY pr.SubmitDate DESC) AS LatestVersionId
FROM Product p
LEFT OUTER JOIN ProductRevision pr ON p.Id = pr.ProductId
You can use a LEFT JOIN like this:
SELECT p.Id, p.Name, p.Price, pr.RevisionId as LatestRevisionId
FROM Product p LEFT OUTER JOIN
(SELECT pr.*,
ROW_NUMBER() OVER (PARTITION BY ProductId ORDER BY SubmitDate DESC) as seqnum
FROM ProductRevision pr
)
ON p.Id = pr.ProductId AND seqnum = 1;
If you want to aggregation other values, then just do:
SELECT p.Id, p.Name, p.Price,
MAX(CASE WHEN seqnum = 1 THEN pr.RevisionId END) as LatestRevisionId
FROM Product p LEFT OUTER JOIN
(SELECT pr.*,
ROW_NUMBER() OVER (PARTITION BY ProductId ORDER BY SubmitDate DESC) as seqnum
FROM ProductRevision pr
)
ON p.Id = pr.ProductId
GROUP BY p.Id, p.Name, p.Price;
This should be the simplest method to accomplish what you want.

How do I select max date for each row from a subquery

Let's say I want to select the 3 bestsellers in a supermarket. To do this, I have to add each sale to get the total for each product:
SELECT TOP(3) *
FROM
(
SELECT
SUM(s.individual_sale) AS totalsales,
p.productID AS ID,
p.productName AS Name
FROM
sales s,
products p
WHERE
1=1
AND p.productID = s.productID
GROUP BY
p.productID,
p.productName
) AS top_sellers
ORDER BY
top_sellers.totalsales DESC
It then returns me something like this:
ID..|.Name.|.totalsales
55.|.milk....|.1000
24.|.candy.|.800
67.|.juice...|.500
Now I want to retrieve a 4th column containing the last sale from each of these items, like querying "MAX saledate" to each one. How do I accomplish that?
EDIT: Adding MAX(s.saledate) isn't helping. It retrieves a date like 01 Jan 2012 to all rows, but if I query MAX(s.saledate) individually for each entry of the table above, it returns the correct date... My question is, how can I add the column MAX(s.saledate) for each product, using the same query that shows the 3 bestsellers.
You could add max(s.saledate) to your query. The subquery is not needed. The syntax t1 join t2 on <predicate> is considered much more readable than from t1, t2 where <predicate>.
select top 3 sum(s.individual_sale) as totalsales
, p.productID as ID,
, p.productName as Name
, max(s.saledate) as MaxSaleDate
from sales s
join products p
on p.productID = s.productID
group by
p.productID
, p.productName
order by
sum(s.individual_sale) desc
SELECT TOP(3) *
FROM
(
SELECT
SUM(s.individual_sale) AS totalsales,
p.productID AS ID,
p.productName AS Name,
MAX(s.saledate) as MaxSaleDate
FROM
sales s,
products p
WHERE
1=1
AND p.productID = s.productID
GROUP BY
p.productID,
p.productName
) AS top_sellers
ORDER BY
top_sellers.totalsales DESC
Add MAX(saledate) to your exisitng query.
SELECT TOP(3) *
FROM
(
SELECT
SUM(s.individual_sale) AS totalsales,
p.productID AS ID,
p.productName AS Name,
MAX(saleDate)
FROM
sales s,
products p
WHERE
1=1
AND p.productID = s.productID
GROUP BY
p.productID,
p.productName
) AS top_sellers
ORDER BY
top_sellers.totalsales DESC