Join 2 tables to produce desired output - mysql

I have 2 tables as following:
Products table:
ProductID Name
1 Condensed cheese
2 Milk
Prices table:
ProductID Currency Price
2 EUR 1.50
2 USD 1.74
2 JPY 194.624
1 EUR 0.99
1 USD 1.15
I am learning SQL and wondering what would be SQL statement to join 2 above tables to produce this output:
ProductID Name EUR USD JPY
1 Condensed cheese 0.99 1.15 NULL
2 Milk 1.50 1.74 194.624

you can use max() function with case when
select t1.ProductID ,t1.Name,
max(case when t2.Currenc= 'EUR' then Price end) as EUR,
max(case when t2.Currenc= 'USD' then Price end) as USD,
max(case when t2.Currenc= 'JPY' then Price end) as JPY
from
Products t1 join Prices t2 on t1.ProductID =t2.ProductID
group by t1.ProductID ,t1.Name

It is a Pivot Table problem. You will need to use conditional aggregation with Group By clause.
Do an Inner Join between the two tables using ProductID.
We do a Group By on ProductId and Name, since you want a single row for a productid with all the prices in the same row.
Now, we will use conditional function If() to determine price for a specific currency column. If the currency code matches for that column, we consider that price value, else we consider null. So, for example, in a column aliased EUR, we will have null values for rest of the currencies (except EUR). We will then use Max() function to ensure that we consider the corresponding currency price only.
If there is no price value for a specific currency in the Prices table, it shall come as null value (all currencies will show null and Max(null, null, ...) = null
Eventually we Order By ProductID ASC to get the result sorted in ascending order by ProductID.
Try the following query:
SELECT pdt.ProductID,
pdt.Name,
MAX( IF(prc.Currency = 'EUR', prc.Price, NULL) ) AS EUR,
MAX( IF(prc.Currency = 'USD', prc.Price, NULL) ) AS USD,
MAX( IF(prc.Currency = 'JPY', prc.Price, NULL) ) AS JPY
FROM Products AS pdt
INNER JOIN Prices AS prc ON prc.ProductID = pdt.ProductID
GROUP BY pdt.ProductID, pdt.Name
ORDER BY pdt.ProductID ASC

Related

How to fetch price for all suppliers in joined table

I have the following query
SELECT
price
FROM prices
left join suppliers s on prices.id_supplier = s.id_supplier
AND prices.id_product = 57;
Table structures are as follows:
Suppliers:
id_supplier
name
1
Supplier 1
2
Supplier 2
3
Supplier 3
Prices
id_pk
id_product
date
price
id_supplier
1
57
2022-12-29
4.99
1
2
57
2022-12-29
6.99
2
So based on the data above, I wish to create a query which fetches all prices for all supplier for a given product, even for Supplier 3 (which we do not have a price for in which case it should return 0)
Outpout I require is as follows:
id_supplier
price
1
4.99
2
6.99
3
0
Is this possible?
You have the tables joined in the wrong order.
You want all rows from supplier, so that's the LEFT table.
SELECT
s.*,
COALESCE(p.price, 0)
FROM
suppliers s
LEFT JOIN
prices p
ON p.id_supplier = s.id_supplier
AND p.id_product = 57
SELECT
CASE WHEN price = 57 THEN 57
WHEN s.id_supplier IS NULL THEN 0
END AS price
FROM prices
LEFT JOIN suppliers s on prices.id_supplier = s.id_supplier
If I am understanding your problem correctly then this should work. Using case statement will get you price as 57 when price is 57 and when id_supplier IS NULL it will assign 0 to that row. Let me know if this helps.
Edit:
SELECT
s.id_supplier,
CASE WHEN price = 57 THEN 57
WHEN price IS NULL THEN 0
END AS price
FROM prices
RIGHT JOIN suppliers s on prices.id_supplier = s.id_supplier
This query will select all the suppliers where price is either 57 or null.

How get two fields of different records in one record Mysql

I have one table with this content(There are more fields that are not relevant):
A transaction can be purchase or sale. A purchase can be id_factura or id_albaran, if it's purchase id_factura, id_albaran is Null and vice versa, the sale is the same. But a sale can have two records with the same imei, as we see in the example: id_purchasesale 2 and 3 (in this case it will always have the same price, in example 250).
The imei field can only exist as a purchase once (invoice_id or albaran_id) and as a sale once or twice.
If there is a purchase and there is no sale of the same imei you don't have to show it.
TABLE purchasesale
id_purchasesale transaction id_factura id_albaran Model imei price
1 purchase 1 Null Samsung 30888 200
2 sale 1 Null Samsung 30888 250
3 sale Null 1 Samsung 30888 250
4 purchase Null 1 Apple 52101 300
5 sale 1 Null Apple 52101 380
6 purchase 2 Null Motorola 77520 300
7 sale 2 Null Motorola 77520 350
8 purchase 3 Null Xiaomi 29102 150
What I want to obtain is the following result, a field with the purchase price, another field with the sale price and another field with the profit of these two fields and the model field.
imei price_purchase price_sale profit Model
30888 200 250 50 Samsung
52101 300 380 80 Apple
77520 300 350 50 Xiaomi
Your table design is a mess. If you can change it I would split this table in three separate tables, one for purchases, one for sales, and one for phones.
However, with the current situation, this should do what you require:
SELECT
t1.imei as imei,
t1.price as price_purchase,
t2.price as price_sale,
(t2.price - t1.price) as profit,
t1.model as model
FROM purchasesale t1, purchasesale t2
WHERE t1.imei = t2.imei and
t1.transaction = 'purchase' and
t2.transaction = 'sale'
Hope I helped!
you sould use the same table two using alias and filtering by sale and purchase
select a.imei
, a.model
, a.price as price_purchase
, b.price as price_sale
, b.price - a.price as profit
from purchasesale a
inner join purchasesale b on a.imei = b.imei
and a.transaction ='purchase'
and b.transaction ='sale'
You can try below -
select imeid,
max(case when transaction='purchase' then price else 0 end) as purchase_price,
max(case when transaction='sale' then price else 0 end) as sale_price,
max(case when transaction='sale' then price else 0 end)-max(case when transaction='purchase' then price else 0 end) as profit,
model
from tablename
where transaction in ('purchase','sale')
group by imeid,model
having count(distinct transaction)=2

How can I get the price to depend on id using MySQL

I multiply the price and SUM of quantity to get the total. The problem when I multiply the two-column from the different table I get the wrong result. Price is not matched to the sup_med_id it just took the first row which is 10. How can I get the price to depends on sup_med_id?
sup_med_id price sup_id rec_order_dtls sup_med_id rec_quantity
1 10.00 2 1 1 200
2 12.00 2 2 2 100
date_id date
1 2019-01-01
2 2019-01-02
... ...
Output
Month Quantity Total Supplier
...
Jul 0 0 NULL
Aug 300 3000 Unilever
I didn't put all the data and tables above.
I wish this was the result below.
Expected Output
Month Quantity Total Supplier
...
Jul 0 0 NULL
Aug 300 3200 Unilever
SELECT DATE_FORMAT(tbl_date.date, '%b')
AS Month,
COUNT(tbl_purchase_received_details.purchase_received_id)
AS Total_Order,
SUM(IFNULL(tbl_purchase_received_details.received_quantity,0))
AS Quantity,
IFNULL((tbl_supplier_medicine.price) *
SUM(tbl_purchase_received_details.received_quantity),0)
AS Total_Amount,
tbl_supplier.supplier_name
AS Supplier FROM tbl_date
LEFT JOIN
tbl_purchase_received ON tbl_purchase_received.date_received = tbl_date.date
LEFT JOIN
tbl_purchase_received_details ON tbl_purchase_received.purchase_received_id
= tbl_purchase_received_details.purchase_received_id
LEFT JOIN
tbl_supplier_medicine ON tbl_supplier_medicine.supplier_medicine_id =
tbl_purchase_received_details.supplier_medicine_id
LEFT JOIN tbl_supplier ON tbl_supplier.supplier_id =
tbl_supplier_medicine.supplier_id
WHERE YEAR(tbl_date.date) = YEAR(NOW())
GROUP BY DATE_FORMAT(tbl_date.date, '%b')
ORDER BY tbl_date.date
Hello If I understand your question properly then you need to multiply quantity and price to get the total.
If that is correct then you can use the below query :
select tt.rec_quantity as quantity, (price * rec_quantity) as total from temp t inner join temp2 tt on t.sup_med_id=tt.sup_med_id;
If one of the tables can have no match data then you can use left join.
Let me know if you need help.

SQL : Show date when product was present in 6 months of data

I am pretty new to sql but have a problem I can't seem to find an answer to yet.
I need to find the month where the number of months a product in a certain segment showed up in a report is equal to 6. However, a product may not show up in sequential months, shows up multiple times a month, and some products have not beensold in 6 months yet.
I have a database with the following attributes:
Entry_Id Product_Name Sold_Date Payment_Amount Segment
======================================================================
112341 ABC Product 2017/12/20 10.50 Segment 1
112342 123 Product 2016/08/21 11.20 Segment 1
112343 ABC Product 2017/12/20 11.50 Segment 1
112344 123 Product 2017/08/21 11.20 Segment 1
112345 123 Product 2017/06/12 11.20 Segment 1
112346 123 Product 2016/06/21 11.20 Segment 1
112347 123 Product 2016/05/02 11.20 Segment 1
112348 123 Product 2015/04/01 11.20 Segment 1
112348 123 Product 2018/01/05 11.20 Segment 1
I would like to get something to the following effect
Product_Name Date where N = 6 segment
=================================================
ABC Product N/A Segment 1
123 Product 2018/01/05 Segment 1
The Day of month does not matter, just the month where the the number of months it has shown up in is equal to 6.
This is my first question and I will be as active as possible, please ask any clarifying questions.
Thank you!
Use GROUP BY and COUNT() to count the number of months that each product was sold in, and HAVING to filter the results.
SELECT t1.product_name, max_date, segment
FROM yourTable AS t1
JOIN (
SELECT product_name, MAX(sold_date) AS max_date
FROM yourTable
GROUP BY product_name
HAVING COUNT(DISTINCT YEAR(sold_date), MONTH(sold_date)) >= 6
) AS t2 ON t1.product_name = t2.product_name AND t1.sold_date = t2.max_date
The t2 subquery finds all the products that were sold in at least 6 different months. Joining that with the table finds the row with the last date, so its segment column can be selected.
If you want to include the products that weren't sold in at least 6 months, with N/A in that column, you can move the test out of the subquery.
SELECT product_name, IF(month_count >= 6, max_date, "N/A") AS last_date, segment
FROM yourTable AS t1
JOIN (
SELECT product_name, MAX(sold_date) AS max_date, COUNT(DISTINCT YEAR(sold_date), MONTH(sold_date)) as month_count
FROM yourTable
GROUP BY product_name
) AS t2 ON t1.product_name = t2.product_name AND t1.sold_date = t2.max_date
You can do this with a correlated subquery:
select t.*
from t
where 6 = (select count(distinct year(t2.sold_date), month(t2.sold_date))
from t t2
where t2.segment = t.segment and and t2.product = t.product and
t2.sold_date <= t.sold_date
);
Because of the count(distinct), this will show all records from the 6th month. Also, this is not particularly efficient, but it does use just standard SQL.
You can summarize this to one row per segment/product:
select t.segment, t.product, min(t.sold_date)
from t
where 6 = (select count(distinct year(t2.sold_date), month(t2.sold_date))
from t t2
where t2.segment = t.segment and and t2.product = t.product and
t2.sold_date <= t.sold_date
)
group by t.segment, t.product;

Retrieve and compute prices in MySQL using conditions

I want to retrieve/compute the price on a given date for different assets, depending on the side of the transaction. Prior to 2000, I have mid quotes, afterwards I have bid and ask or offer quotes, so I would like the price to be the average of these two quotes. More precisely:
SELECT date, price,
CASE WHEN side='' THEN 'price_mid'
WHEN side='A' THEN 'price_ask'
WHEN side='B' THEN 'price_bid'
WHEN side='O' THEN 'price_offer'
END as prices
FROM table
WHERE asset = 'a';
How can I then compute the price in a new column, having the price_mid (prior to 2000) and (price_bid+price_ask)/2 or (price_bid+price_offer)/2 afterwards?
E.g.: Let's say I have the following situation:
date price prices
1 1 price_mid
2 1.1 price_mid
3 0.9 price_bid
3 1.2 price_ask
4 1.3 price_offer
4 1.1 price_bid
And I would like to have:
date final_price
1 1
2 1.1
3 1.05
4 1.2
I understand you need the average for only some dates. Maybe the following does what you want:
SELECT date, AVG(price) as AvgValue
FROM prices
WHERE date >= 2
AND prices in ('price_ask','price_offer','price_bid')
GROUP BY date
UNION
SELECT date, price as AvgValue
FROM prices
WHERE date < 2
AND prices = 'price_mid'
GROUP BY date
UNION
SELECT date, price as AvgValue
FROM prices p
WHERE date >= 2
AND prices = 'price_mid'
AND NOT EXISTS (SELECT 1 FROM prices p2 where p2.date = p.date AND p2.prices in ('price_ask','price_offer','price_bid'))
GROUP BY date
ORDER BY DATE ASC
Something like this
SELECT `date`, AVG(price) AS final_price FROM tbl GROUP BY 1
Tried something, it did not work, nevertheless maybe that helps..
This is a changed version of the query you already have, but it does not save a kind of state, it only has all the values on the right places.
SELECT
date,
CASE WHEN side = '' THEN price
ELSE NULL
END as price_mid,
CASE WHEN side = 'A' THEN price
ELSE NULL
END as price_ask,
CASE WHEN side = 'B' THEN price
ELSE NULL
END as price_bid,
CASE WHEN side = '' THEN price
ELSE NULL
END as price_offer
FROM
table
WHERE
asset = 'a';
What should give you:
date price_mid price_ask price_bid price_offer
1 1 NULL NULL NULL
2 1.1 NULL NULL NULL
3 NULL NULL 0.9 NULL
3 NULL 1.2 NULL NULL
4 NULL NULL NULL 1,4
4 NULL NULL 1.1 NULL
Now on that table you can check with IS NULL or take the SUM()or the MAX() per date, so you can switch through your cases on one line.