SQL NESTED JOIN NOT USING WHERE - sql

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

Related

Use 1 SQL query to join 3 tables and find the category of products that generates the most revenue for each customer segment

I am using SQLite3 for this following query.
I have a table called "products" that looks like this:
I have a table called "transactions" that looks like this:
I have a table called "segments" that looks like this:
For each active segment, I want to find the category that produces the highest revenue.
I think that I know how to do this in 3 different queries.
create table table1 as
SELECT s.seg_name, p.category, t.item_qty * t.item_price as revenue
from segments s
JOIN
transactions t
on s.cust_id = t.cust_id
JOIN products p
on p.prod_id = t.prod_id
where s.active_flag = 'Y'
order by s.seg_name, p.category
;
create table table2 as
select seg_name, category, sum(revenue) as revenue
from table1
group by seg_name, category;
select seg_name, category, max(revenue) as revenue
from table2
group by seg_name;
How can I do it in 1 query?
here is one way :
select seg_name,category,revenue
from (
select
s.seg_name,
p.category,
sum(t.item_qty * t.item_price) as revenue,
rank() over (partition by seg_name order by sum(t.item_qty * t.item_price) desc) rn
from segments s
join transactions t on s.cust_id = t.cust_id
join products p on p.prod_id = t.prod_id
where s.active_flag = 'Y'
group by seg_name, p.category
) t where rn = 1

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;

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

How can I select lastest purchase price before a selling date?

I have 5 tables in my database, products, purchase_orders, invoice, invoice_details, and product_prices and their schema are like below.
Table: products
id
trade_name
Table: purchase_orders
id
product_id
created
Table: invoices
id
created
Table invoice_details
id
invoice_id
product_id
price_id
Table product_prices
id
retail_price
effective_from
effective_to
I think that I need to somehow join or check created on purchase_orders to created on invoices. So, I started with getting drug id, invoice date.
select d.id as drug_id
, i.created as invoice_created
, dp.retail_price
from drugs d
inner join invoice_details id
on d.id = id.drug_id
inner join invoices i
on i.id = id.invoice_id
inner join drug_prices dp
on dp.id = id.price_id
The next step is to match created on invoice that I have to created on purchase_orders which I haven't figured it out.
inner join (
select drug_id
, purchase_price
, ISNULL(created, CONVERT(DATETIME, '2015-10-07 01:37:12.370')) as created
from purchase_orders po
) as prepared_po
on prepared_po.created <= i.created
How can I get the lasted purchase price for each item that I sold?
Here's a simplified version of the logic you need (I renamed your columns so that it's easier to see which are which without doing all the intermediary joins you've already written yourself):
;With CTE as (select a.productID, a.saledate, b.price, b.purchasedate
, row_number() over (partition by a.productID, a.saledate
order by b.purchasedate desc) RN
from sales a
left join purchases b
on a.productID = b.productID and a.saledate >= b.purchasedate
)
Select productID, saledate, price, purchasedate
from CTE where RN = 1
Basically, you join to get all purchase records up to the sale date, then use row_number to find the latest one.
http://sqlfiddle.com/#!6/a0f68/2/0

Could not get the expected query with SQL Server

I´m trying to do a SQL query but I couldn´t get the expected result. I really don´t know what is going wrong.
I have a table Product which contains (product_id, title) and other table Product_Variation which contains (product_variation_id, product_id, description, gender, price)
Basically, I have a product. For each product, have N variations.
e.g
Product: title "I have no idea"
Product_Variation: description "T-Shirt", gender "Male", price "59.90"
What I need is select Product and Product_Variation showing only the product with the lowest price.
I don´t care if a product has t-shirt, jacket or anything else as variation. I just need to get the variation which has the lowest price.
My query is:
SELECT b.product_id, b.title, MIN(b.price) as price, b.gender
FROM (
SELECT p.product_id, p.title, MIN(pv.price) AS price, pv.gender
FROM products p
join product_variation pv ON pv.product_id = p.product_id
GROUP BY p.product_id, p.title, pv.price, pv.gender
) b
GROUP BY b.product_id, b.title, b.price, b.gender
Pls, see my example in SQL Fiddle
Thanks!
Since you're using SQL 2008 you can use ROW_NUMBER to find the row with the lowest price:
SELECT *
FROM products p
INNER JOIN
(SELECT
product_id,
Description,
Gender,
Price,
ROW_NUMBER() OVER(PARTITION BY product_id ORDER BY price) Row
FROM product_variation )
pv ON pv.product_id = p.product_id
AND Row = 1
If you have two variations with the same price you'll get one random row.
-- Solution #1
SELECT *
FROM
(
SELECT p.product_id, p.title,
pv.price, pv.gender,
ROW_NUMBER() OVER(PARTITION BY p.product_id ORDER BY pv.price) AS row_num
FROM products p
join product_variation pv ON pv.product_id = p.product_id
) src
WHERE src.row_num = 1
-- Solution #2
SELECT p.product_id, p.title,
x.price, x.gender
FROM products p
cross apply
(
SELECT TOP(1) pv.price, pv.gender
FROM product_variation pv
WHERE pv.product_id = p.product_id
ORDER BY pv.price
) x
You can use the rank() window function to order stuff within a partition (group), but giving equal items the same rank:
;With b as (
Select
p.product_id,
p.title,
pv.price,
pv.gender,
rank() over(partition by p.product_id order by pv.price) rk
From
products p
Inner Join
product_variation pv
On pv.product_id = p.product_id
)
Select
b.product_id,
b.title,
b.price,
b.gender
From
b
Where
rk = 1
If you only want one per product even if there are equal products, use row_number() instead of rank()
Example Fiddle