List vendors, and lowest priced product SQL - sql

I am trying to join 2 tables and create a new field returning the lowest value of a product. I've tried many variations and can't seem to get it to work.
SELECT DISTINCT VENDOR.*, PRODUCT.P_PRICE, PRODUCT.LOWEST_PRICE AS MIN(PRODUCT.P_PRICE)
FROM PRODUCT
INNER JOIN VENDOR
ON VENDOR.V_CODE = PRODUCT.V_CODE
ORDER BY VENDOR.V_NAME

You can use this, This will order from Minimum price vendor product
SELECT VENDOR.V_NAME, MIN(PRODUCT.P_PRICE) AS LOWEST_PRICE
FROM VENDOR
INNER JOIN PRODUCT
ON VENDOR.V_CODE = PRODUCT.V_CODE
GROUP BY VENDOR.V_NAME
ORDER BY LOWEST_PRICE
SQL FIDDLE:- http://sqlfiddle.com/#!3/467c8/2

If you are looking for the lowest price by vendor, use group by and min:
SELECT VENDOR.V_NAME, MIN(PRODUCT.P_PRICE) AS LOWEST_PRICE
FROM PRODUCT
INNER JOIN VENDOR
ON VENDOR.V_CODE = PRODUCT.V_CODE
GROUP BY VENDOR.V_NAME
ORDER BY VENDOR.V_NAME

Not knowing how your schema is defined try this:
SELECT
VENDOR.V_NAME,
PRODUCT.P_PRICE AS [VENDOR PRICE],
MIN(PRODUCT.P_PRICE) AS [LOWEST PRICE]
FROM
PRODUCT
INNER JOIN VENDOR ON VENDOR.V_CODE = PRODUCT.V_CODE
GROUP BY
VENDOR.V_NAME,PRODUCT.P_PRICE
ORDER BY
VENDOR.V_NAME

If you want the lowest price product per vendor, I would suggest using window functions:
select pv.*
from (select v.v_name, p.p_name, p.p_price
row_number() over (partition by p.v_code order by p.p_price asc) as seqnum
from vendor v join
product p
on v.v_code = p.v_code
) pv
where seqnum = 1

Related

SQL NESTED JOIN NOT USING WHERE

What is the current price of each product? Display product code, product description, unit, and its current price. Always assume that NOT ALL products HAVE unit price BUT you need to display it even if it has no unit price on it. without using WHERE script
Product Table
prodCode
description
unit
PriceHist Table
prodCode
effDate
unitPrice
This is my work... Please Help me to improve my anwswer.
SELECT p.prodCode, p.description, p.unit, MAX(ph.unitPrice) "Current Price"
FROM product p
INNER JOIN priceHist AS ph
ON p.prodCode = ph.prodCode
GROUP BY p.prodCode, p.description, p.unit
ORDER BY MAX(ph.unitPrice);
Someone said I NEED TO USE PRICEHIST TWICE
User window functions and left join:
select . . . -- whatever columns you want
from products p left join
(select ph.*,
row_number() over (partition by p.prodcode order by effdate desc) as seqnum
from pricehist ph
) ph
on ph.prodcode = p.prodcode and ph.seqnum = 1;
Try this:
SELECT a.prodCode, a.description, a.unit, SUM(b.unitPrice)
FROM ProductTable a
LEFT JOIN PriceHistTable b ON a.prodCode = b.prodCode
GROUP BY a.prodCode, a.description, a.unit, b.unitPrice
Assuming you want to select unitPrice for prodCode with latest effDate, below query should work. Explanation in comments.
select x.prodCode, x.description, x.unit, y.unitPrice
from Product x
left join (
--- Create a table y with one row per (prodCode, effDate)
--- choosing the latest effDate per prodCode
select a.prodCode, a.effDate, a.unitPrice
from PriceHist a
join (
--- Create b as (prodCode, effDate)
select prodCode, max(effDate) as maxEffDate
from PriceHist
group by prodCode
) b
on a.prodCode = b.prodCode and a.effDate = b.maxEffDate
) y
on x.prodCode = y.prodCode

SQL Nested join showing the current price of each product and using MAX()

What is the current price of each product? Display product code, product description, unit, and its current price.
HINT: You will use MAX(). This is a nested join.
PRODUCT TABLE
prodCode
description
unit
PRICE HIST
effDate
prodCode
unitPrice
Can someone help me to improve my script ?
this is my script, im using ibm.cloud
SELECT p.prodCode, p.description, p.unit, MAX(ph.unitPrice) "Current Price"
FROM product p
FULL JOIN priceHist ph
ON p.prodCode = ph.prodCode
GROUP BY p.prodCode, p.description, p.unit
ORDER BY MAX (ph.unitPrice);
This will give you each product and its latest price in a table.
SELECT p.prodCode, p.description, p.unit,
(SELECT unitPrice
FROM priceHist
WHERE prodCode = p.prodCode
ORDER BY effDate DESC
LIMIT 1
) "Current Price"
FROM product p;
I think full join is not required (use left join) and you can use the where clause as follows:
SELECT p.prodCode, p.description, p.unit, coalesce(ph.unitPrice,p.unitprice) "Current Price"
FROM product p
Left JOIN priceHist ph ON p.prodCode = ph.prodCode
WHERE ph.prodcode is null
or ph.date_col = (select max(phh.date_col) from pricehist phh on phh.prodcode = ph.prodcode)
In DB2, I would recommend window functions:
SELECT p.prodCode, p.description, p.unit, ph.unitPrice as current_price
FROM product p LEFT JOIN
(SELECT ph.*,
ROW_NUMBER() OVER (PARTITION BY prodCode ORDER BY effdate) as seqnum
FROM priceHist ph
) ph
ON ph.prodCode = p.prodCode AND ph.seqnum = 1
ORDER BY ph.unitPrice;

Include the sales revenue amount into the select query

I also have a (somewhat) similar scenario as from this guy.
This is my current code:
SELECT Vendor_Name, Product
FROM (
SELECT v.Vendor_Name, p.Description AS Product, ROW_NUMBER() OVER (PARTITION BY v.Vendor_Key ORDER BY SUM(sf.Price * sf.Quantity) DESC) AS seqnum
FROM SalesFacts sf JOIN Vendor v
ON sf.Vendor_Key = v.Vendor_Key JOIN Product p
ON sf.Product_Key = p.Product_Key
GROUP BY v.Vendor_Key, v.Vendor_Name, p.Product_Key, p.Description
) vp
WHERE vp.seqnum = 1
The result of the query is show as below:
What the above query did was to extract the top-grossing product for each vendor from the entire database, or in other words, the query obtained the highest-revenue product per vendor.
I wanted to add in a new column, which is Sales Revenue, which calculation can be derived as such:
price of item * quantity. I wanted to add in the new column so that i can see see how much revenue the vendor earned from their respective best-selling products.
How do i obtain the same result with the inclusion of sales revenue column?
The way your question is asked, you just want to return this column from the subquery so it can be accessed in the outer query:
SELECT Vendor_Name, Product, Sales_Revenue
FROM (
SELECT
v.Vendor_Name,
p.Description AS Product,
SUM(sf.Price * sf.Quantity) Sales_Revenue
ROW_NUMBER() OVER (PARTITION BY v.Vendor_Key ORDER BY SUM(sf.Price * sf.Quantity) DESC) AS seqnum
FROM SalesFacts sf JOIN Vendor v
ON sf.Vendor_Key = v.Vendor_Key JOIN Product p
ON sf.Product_Key = p.Product_Key
GROUP BY v.Vendor_Key, v.Vendor_Name, p.Product_Key, p.Description
) vp
WHERE vp.seqnum = 1

Obtain the top-grossing product for each individual vendor

How do I obtain the top-grossing product for each individual vendor?
I came up with this so far and can't seem to proceed.
select vendor.Vendor_Name, Product.category AS Product
, SUM(SalesFacts.Price * SalesFacts.Quantity) AS [Total Revenue]
FROM Vendor, Product, SalesFacts
WHERE SalesFacts.Vendor_Key = Vendor.Vendor_Key
AND SalesFacts.Product_Key = Product.Product_Key
GROUP BY vendor.Vendor_Name, product.Category
ORDER BY [Total Revenue] DESC;
(Product_Key and Vendor_Key are Foreign Key)
select vendor.Vendor_Name,Product.category AS Product,
MAX(SalesFacts.Price * SalesFacts.Quantity) OVER (PARTITION BY
SalesFacts.Vendor_Key,SalesFacts.Product_Key ORDER BY SalesFacts.Vendor_Key ) AS
[Total Revenue] FROM Vendor
,Product,SalesFacts WHERE SalesFacts.Vendor_Key = Vendor.Vendor_Key AND
SalesFacts.Product_Key = Product.Product_Key
--GROUP BY vendor.Vendor_Name,product.Category,SalesFacts.Price,SalesFacts.Quantity
ORDER BY [Total Revenue] DESC;
You can use this.
SELECT * FROM (
SELECT
vendor.Vendor_Name,
Product.Category AS Product,
ROW_NUMBER() OVER(PARTITION BY vendor.Vendor_Name ORDER BY SUM(SalesFacts.Price * SalesFacts.Quantity) DESC) RN
FROM Vendor
INNER JOIN SalesFacts ON SalesFacts.Vendor_Key = Vendor.Vendor_Key
INNER JOIN Product ON SalesFacts.Product_Key = Product.Product_Key
GROUP BY vendor.Vendor_Name, product.Category
) X
WHERE X.RN = 1
I don't see why a "category" should be a product. More importantly, you should be fixing your query:
Never use commas in the FROM clause.
Always use proper, explicit, standard JOIN syntax.
Use meaningful table aliases.
At the product level, this would be:
SELECT Vendor_Name, Product
FROM (SELECT v.Vendor_Name, p.Description AS Product,
ROW_NUMBER() OVER (PARTITION BY v.Vendor_Key ORDER BY SUM(sf.Price * sf.Quantity) DESC) as seqnum
FROM SalesFacts sf JOIN
Vendor v
ON sf.Vendor_Key = v.Vendor_Key JOIN
Product p
ON sf.Product_Key = p.Product_Key
GROUP BY v.Vendor_Key, v.Vendor_Name, p.Product_Key, p.Description
) vp
WHERE vp.seqnum = 1;
This can be easily modified to work for the category, but the question says "product" and the data has something that corresponds to that.

Select data based on latest transaction date for each item

I have a query which I want it to list all latest transaction's price for each stock item. I've tried to use MAX() to list all latest transaction for each item without including the price and it works but when I included the price, the method will not work.
Here's my query
SELECT MAX(DocDate) AS DocDate, StockCode, Price
FROM StockPurchasePriceHistory spph
INNER JOIN Stocks s
ON spph.Stock = s.Id
GROUP BY StockCode, Price
ORDER BY StockCode ASC
Output
use row_number
select * from (SELECT row_number()over(partition by StockCode order by DocDate desc) rn
, StockCode, Price
FROM StockPurchasePriceHistory spph
INNER JOIN Stocks s
ON spph.Stock = s.Id
) a where a.rn=1
try this:
SELECT MAX(DocDate) AS DocDate, StockCode, sum(Price) as Price
FROM StockPurchasePriceHistory spph
INNER JOIN Stocks s
ON spph.Stock = s.Id
GROUP BY StockCode
ORDER BY StockCode ASC
This is a good place to use APPLY:
SELECT spph.DocDate, s.StockCode, spph.Price
FROM Stocks s CROSS APPLY
(SELECT TOP (1) spph.*
FROM StockPurchasePriceHistory spph
WHERE spph.Stock = s.Id
ORDER BY spph.DocDate DESC
) spph;
With an index on StockPurchasePriceHistory(Stock, DocDate desc), I would expect this to be a bit faster than alternatives using window functions and approximately as fast as a correlated subquery.