Select same column from multiple tables with condition and LEFT JOIN - sql

I have two tables with fiew similar columns :
One is for SellOrders
OrderID (PK)| id_seller| id_product| placement_date
And the other is for BuyOrders
OrderID (PK)| id_buyer| id_product| placement_date
With another table Customer concerning customers informations (Buyers and sellers)
id_customer(PK) | name_customer
And a Product table :
id(PK) | name_product
I want to write an SQL statement that will select the first placement_date when the a buy order or sell order was placed for the product and the correspending name_customer + the name_product.
I wrote a query that select the same logic but for only the selling side and I am looking to select the data for both buy and sell side :
SELECT p.name_product, s.placement_date, c.name_customer
FROM Product p
OUTER APPLY (SELECT TOP 1 placement_date, id_seller
FROM Selling
WHERE id_product = p.id
ORDER BY placement_date, OrderID ASC) s
LEFT JOIN Customer c
ON c.id_customer = s.id_seller
From what I have seen UNION SELECT seems to be the way to do this. I added UNION to the OUTER APPLY:
OUTER APPLY (SELECT TOP 1 placement_date, id_seller
FROM Selling
UNION
SELECT TOP 1 placement_date, id_buyer
WHERE id_product = p.id
ORDER BY placement_date, OrderID ASC) s
But I get stuck at the LEFT JOIN with the table Customer.
Any help ?

If I've got it right you want first of union of buy/sell orders
SELECT p.name_product, s.placement_date, c.name_customer
FROM Product p
OUTER APPLY (
SELECT TOP 1 placement_date, id_cust
FROM (
SELECT placement_date, OrderID, id_seller id_cust
FROM SellOrders
WHERE id_product = p.id
UNION
SELECT placement_date, OrderID, id_buyer
FROM BuyOrders
WHERE id_product = p.id
) t
ORDER BY placement_date, OrderID ASC
) s
LEFT JOIN Customer c
ON c.id_customer = s.id_cust

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 Server Query Count Join Table

I have 2 tables are call Suppliers and Products, which products have SupplierID as foreign key.
My question is how to make a query that can show this result
Supplier Name | Total Products
--------------+---------------
Unilever | 20
Kalbe | 50
Jhonson | 70
My table structure
Suppliers => ID, Name
Products => ID, SupplierID, Brand, Price
This is what I tried:
SELECT COUNT(*) AS Total
FROM Products
GROUP BY SupplierID
select
s.Name as 'Supplier Name', count(p.ID) as 'Total Products'
from
Supliers as s
left outer join
Producsts as p on (s.Id = p.SupplierID)
group by
s.Name;
All you need in addition to your query is a sub-query to obtain the name:
SELECT COUNT(*) as Total
, (select Name from Supplier where ID = SupplierID) as [Supplier Name]
FROM Products
GROUP BY SupplierID
you can use left join by SuplierID + subquery for Products group by SuplierID to avoid multi slow query.
select T1.Name as Supplier Name
,T2.cnt as Total Product
from Supliers T1
left join (
select SuplierID,count(1) cnt
from Products
group by SuplierID
) T2 on T1.ID = T2.SuplierID

Get max value from another query

I have problems with some query. I need to get max value and product_name from that query:
select
products.product_name,
sum(product_invoice.product_amount) as total_amount
from
product_invoice
inner join
products on product_invoice.product_id = products.product_id
inner join
invoices on product_invoice.invoice_id = invoices.invoice_id
where
month(invoices.invoice_date) = 2
group by
products.product_name
This query returns a result like this:
product_name | total_amount
--------------+--------------
chairs | 70
ladders | 500
tables | 150
How to get from this: ladders 500?
Select product_name,max(total_amount) from(
select
products.product_name,
sum(product_invoice.product_amount) as total_amount
from product_invoice
inner join products
on product_invoice.product_id = products.product_id
inner join invoices
on product_invoice.invoice_id = invoices.invoice_id
where month(invoices.invoice_date) = 2
group by products.product_name
) outputTable
You can use order by and fetch first 1 row only:
select p.product_name,
sum(pi.product_amount) as total_amount
from product_invoice pi inner join
products p
on pi.product_id = p.product_id inner join
invoices i
on pi.invoice_id = i.invoice_id
where month(i.invoice_date) = 2 -- shouldn't you have the year here too?
group by p.product_name
order by total_amount
fetch first 1 row only;
Not all databases support the ANSI-standard fetch first clause. You may need to use limit, select top, or some other construct.
Note that I have also introduced table aliases -- they make the query easier to write and to read. Also, if you are selecting the month, shouldn't you also be selecting the year?
In older versions of SQL Server, you would use select top 1:
select top (1) p.product_name,
sum(pi.product_amount) as total_amount
from product_invoice pi inner join
products p
on pi.product_id = p.product_id inner join
invoices i
on pi.invoice_id = i.invoice_id
where month(i.invoice_date) = 2 -- shouldn't you have the year here too?
group by p.product_name
order by total_amount;
To get all rows with the top amount, use SELECT TOP (1) WITH TIES . . ..
If you are using SQL Server, then TOP can offer a solution:
SELECT TOP 1
p.product_name,
SUM(pi.product_amount) AS total_amount
FROM product_invoice pi
INNER JOIN products p
ON pi.product_id = p.product_id
INNER JOIN invoices i
ON pi.invoice_id = i.invoice_id
WHERE
MONTH(i.invoice_date) = 2
GROUP BY
p.product_name
ORDER BY
SUM(pi.product_amount) DESC;
Note: If there could be more than one product tied for the top amount, and you want all ties, then use TOP 1 WITH TIES, e.g.
SELECT TOP 1 WITH TIES
... (the same query I have above)

SQL Server inner join after Count and GroupBy

I'm trying to make an eCommerce web site. And at ProductCategory page I have to do a list about Companies that included by Products.
I have a Product table that contains:
ProductID
ProductName
...
MarkID
And I have a Company table that contains:
CompanyID
CompanyName
I want to mix them in a query.
After that code block,
SELECT
CompanyID,
count(CompanyID) as CompanyCount
FROM
Products
GROUP by
CompanyID
I get this result:
CompanyID CompanyCount
-------------------------
1 2
3 1
4 4
after that I just want to inner join that with CompanyName
And want a result like this:
CompanyName CompanyCount
---------------------------
1 2
3 1
4 4
How can I do that?
With a subquery:
SELECT * FROM
(
SELECT CompanyID, count(CompanyID) as CompanyCount
FROM Products
GROUP by CompanyID
) CompanyCounts
INNER JOIN Companies
on CompanyCounts.CompanyId = Companies.CompanyID
If you need this in more places, you may want to create a view for company count.
This can be achieved without a subquery.
SELECT C.CompanyID, C.CompanyName, COUNT(*)
FROM Products P INNER JOIN Companies C ON P.CompanyId = C.CompanyID
GROUP BY C.CompanyID, C.CompanyName
You can use your first select as a subquery to join with Companies table:
SELECT C.CompanyName, Q1.CompanyCount
FROM Companies C
JOIN (
SELECT CompanyID, count(CompanyID) as CompanyCount
FROM Products
GROUP by CompanyID
) Q1
ON Q1.CompanyID = C.CompanyId

SQL - Selecting rows based on priority level

Given the following two tables:
PRODUCT_CATEGORIES
PRODUCT_CATEGORY PRIOTITY
BOOK 100
VIDEO 200
CD 300
PRODUCT_TYPES
PRODUCT_TYPE_ID PRODUCTID PRODUCT_CATEGORY
1 1001 VIDEO
2 1001 CD
3 1002 BOOK
4 1002 VIDEO
5 1003 BOOK
How can i join the two tables so that i select all the rows from PRODUCT_TYPES and where there are duplicate products i only select the one with the highest priority.
For example, for PRODUCTID 1002, i only want the row with a category of VIDEO because VIDEO has a higher priority than BOOK (which is the category of the other 1002 product in the table).
Here is what i have tried but i only seem to get duplicates.
select product_type_id, productid, product_category
from product_types pt
join product_categories pc on (pc.product_category=pt.product_category)
One other way of doing it is to order by product_category in descending order and select the first row where rownum=1 but i suspect that is not the best solution.
WITH recordList
AS
(
SELECT a.Product_TypeID,
a.ProductID,
a.Product_Category,
b.Priority,
ROW_NUMBER() OVER (PARTITION BY a.ProductID
ORDER BY b.Priority) RN
FROM Product_Types a
INNER JOIN Product_Categories b
ON a.Product_Category = b.Product_Category
)
SELECT Product_TypeID,
ProductID,
Product_Category,
Priority
FROM recordList
WHERE RN = 1
SQLFiddle Demo
Try the following query:
SELECT PT.*
FROM PRODUCT_CATEGORIES PC INNER JOIN PRODUCT_TYPES PT
ON PC.PRODUCT_CATEGORY = PT.PRODUCT_CATEGORY
WHERE PC.PRIOTITY = (
SELECT MAX(PRIOTITY) FROM PRODUCT_CATEGORIES IPC
, PRODUCT_TYPES IPT
WHERE IPC.PRODUCT_CATEGORY = IPT.PRODUCT_CATEGORY
AND IPT.PRODUCTID = PT.PRODUCTID)
select
product_type_id,
productid,
product_category
from
PRODUCT_TYPES
where
product_type_id in (
select
max(product_type_id) keep (dense_rank first order by priotity desc)
from
PRODUCT_TYPES
join PRODUCT_CATEGORIES using(product_category)
group by
productid
)
SqlFiddle