I've got stuck at joining two tables and fetching the min value of a price.
I have two tables "tb1" and "tb2".
Both includes ean, price and some other columns.
I wan't to get the cheapest price for same ean's.
So I got this left join:
SELECT price,* FROM tb1 as w left join tb2 as e on w.ean=e.ean
But how do I get the cheapest price?
I know MIN() but the problem is, the min price could be in tb1 or tb2...
Hope you could help me :)
Regards :)
You can use the following solution using a sub-select with UNION ALL to merge the tables into one (tbAll):
SELECT ean, MIN(price) FROM (
SELECT ean, price FROM tb1
UNION ALL
SELECT ean, price FROM tb2
) tbAll
GROUP BY ean
... or another solution using the LEFT JOIN:
SELECT w.ean, MIN(LEAST(w.price, e.price))
FROM tb1 AS w LEFT JOIN tb2 AS e ON w.ean = e.ean
GROUP BY w.ean
In case you need additional information, you can use the UNION ALL solution with additional ROW_NUMBER (available since MySQL 8.0):
SELECT t.ean, t.price, t.merchant FROM (
SELECT ean, price, merchant, ROW_NUMBER() OVER (PARTITION BY ean ORDER BY ean, price) AS rn
FROM (
SELECT ean, price, merchant FROM tb1
UNION ALL
SELECT ean, price, merchant FROM tb2
) tbAll
)t WHERE t.rn = 1
... or in case you are using a MySQL version earlier 8.0 you can use the following:
SELECT t.ean, t.price, t.merchant FROM (
SELECT ean, price, merchant, IF(#prev <> ean, #rn:=0, #rn), #prev:=ean, #rn:=#rn+1 AS rn
FROM (
SELECT ean, price, merchant FROM tb1
UNION ALL
SELECT ean, price, merchant FROM tb2
ORDER BY ean, price
) tbAll JOIN (SELECT #rn:=0) init_rn JOIN (SELECT #prev:='') init_prev
)t WHERE t.rn = 1
demo on dbfiddle.uk
Use Case
CASE
WHEN w.price < e.price THEN w.price
ELSE e.price
END AS MINPRICE
Related
My issue with SQL function, is that I often mix SUM / COUNT, or even where I can put a WHERE clause and a GROUP BY, short version, SQL is one of my flaws.
Ok, now here's my current issue, I need to make a SQL function (in my PHP Model) that get the number of order I had "today" and their total cost, but I need to separate the result by country (sorry for my english) , for example the result I want should look like this (let's say I had 20 orders today) :
U.S : 15 orders (for a total of 288$) , CANADA : 5 orders (for a total of 94$)
I tried many things, and the only two that didn"t give me an error were these two (but far from the result I need) :
SELECT sum(o.amount) AS totalmoney, p.name, p.id, p.name_clean, p.iso_code
FROM orders AS o
LEFT JOIN customers AS c ON o.id_customer = c.id
LEFT JOIN countries AS p ON c.country = p.id
WHERE DATE(o.date_create) = CURDATE()
SELECT sum(o.amount) AS totalmoney, o.date_create, p.name, COUNT(p.id) AS totalpays,
p.name_clean, p.iso_code, c.country
FROM orders AS o
LEFT JOIN customers AS c ON o.id_customer = c.id
LEFT JOIN countries AS p ON c.country = p.id
GROUP BY o.date_create
My three tables are (table name : column usefull) :
countries : id - name
customers : id - country_id
orders : id - id_customer - amount ($) - date_create
Can you please help me?
Thank you for your time.
------------- EDIT WITH THE ANSWER I USED ---------------
Thanks to everyone who participate and helped me to have a better understanding of SQL.
SELECT sum(orders.amount) total, countries.name
FROM orders
INNER JOIN customers ON orders.id_customer = customers.id
INNER JOIN countries ON countries.id = customers.country_id
WHERE orders.date_create = ?
GROUP BY customers.id
It's exactly what I needed.
You’re wanting to group by country on a certain date, therefore your group by is country, and the where is the date:
SELECT sum(orders.amount) total, countries.name
FROM orders
INNER JOIN customers ON orders.id_customer = customers.id
INNER JOIN countries ON countries.id = customers.country_id
WHERE orders.date_create = ?
GROUP BY customers.id
Inner join is appropriate here, because the joins should only produce a single row for customer and country per order.
Try with that:
-- PostgreSQL
drop table orders;
drop table countries;
drop table customers;
CREATE TABLE countries
(
id integer not null,
name varchar(200)
);
insert into countries(id, name) values (1, 'MEXICO');
insert into countries(id, name) values (2, 'US');
insert into countries(id, name) values (3, 'CANADA');
create table customers
(
id integer not null,
name varchar(200),
country integer not null
);
insert into customers(id, name, country) values (1, 'Huey',1);
insert into customers(id, name, country) values (2, 'Dewey',2);
insert into customers(id, name, country) values (3, 'Louie',3);
create table orders
(
id integer not null,
id_customer integer not null,
amount double precision,
date_create date
);
insert into orders values (1, 1, 500.0, '20200103');
insert into orders values (2, 1, 1000, '20200103');
insert into orders values (3, 2, 500, '20200103');
insert into orders values (4, 3, 500, '20200103');
insert into orders values (5, 1, 500, '20200103');
SELECT COUNT(*) AS num_orders, sum(o.amount) AS totalmoney, p.name
FROM orders AS o
INNER JOIN customers AS c ON o.id_customer = c.id
INNER JOIN countries AS p ON c.country = p.id
WHERE DATE(o.date_create) = '20200103'
group by p.name
order by num_orders desc;
you can use over whith sum and count
select sum(amount) over(partition by contry_id) as totalamount,
count(contry_id) over(partition by contry_id) as totalcount,
name, ord.id
from orders ord left join customers cus on ord.customer_id = cus.id
left join countries con on cus.contry_id = con.id
where date_create = [date] --using string as a pseudo date when testing, so change is needed
here is a db<>fiddle with some pseudo data.
this will also get the data group by created date which match the OP need more imo.
select distinct sum(amount) over(partition by contry_id,date_create) as totalamount,
count(contry_id) over(partition by contry_id,date_create) as totalcount,
name, date_create
from orders ord left join customers cus on ord.customer_id = cus.id
left join countries con on cus.contry_id = con.id
pros with window function : over is that you can have different aggregate function with different 'condition' and don't need to group by every non aggregate column which usually lead to a lot of subqueries.
This should do what you want it to do:
SELECT
c.name,
sq.totalmoney
FROM
countries as c
JOIN
(SELECT
SUM(o.amount) AS totalmoney,
c.id
FROM
(SELECT
*
FROM
orders
WHERE
DATE(date_create) = CURDATE()
) AS o
JOIN
customers AS c
ON
o.id_customer = c.id
GROUP BY c.id) AS sq
on c.id = sq.id;
I have 3 tables on mySQL database. product, stock_in, stock_out. I want to sum total stock in and stock out of each product by product_id.
I use this query below. But it gives me some false answers.
SELECT product.Product_Name, SUM(stock_in.StockInQuantity) as stockin, S
SUM(stock_out.Quantity) as stockout
FROM product, stock_in, stock_out
WHERE stock_in.Product_ID=product.Product_ID
and stock_out.Product_ID=product.Product_ID
GROUP BY product.Product_ID**
But if I use separate queries for stockin and stockout, results are correct.
SELECT Product_Name, SUM(StockInQuantity) as stockin
FROM product, stock_in
WHERE stock_in.Product_ID=product.Product_ID
GROUP BY product.Product_ID
SELECT Product_Name, SUM(Quantity) as stockout
FROM product, stock_out
WHERE stock_out.Product_ID=product.Product_ID
GROUP BY product.Product_ID**
So please give me a solution to find the result in one query or to echo results of two query results in one table..
You can try below query:
SELECT p.product_name AS Product_Name,
COALESCE(SUM(si.stockin), 0) AS total_stockin,
COALESCE(SUM(so.stockout), 0) AS total_stockout,
FROM product p
LEFT JOIN (SELECT Product_ID, SUM(StockInQuantity) AS stockin
FROM stock_in
GROUP BY Product_ID) si ON si.Product_ID = p.Product_ID
LEFT JOIN (SELECT Product_ID, SUM(Quantity) AS stockout
FROM stock_out
GROUP BY Product_ID) so ON so.Product_ID = p.Product_ID
GROUP BY Product_Name
I need sum quantity in a different field with alias.
Image
I don't what your two table names are but this should work. You're trying to aggregate on idMaterial after joining on idMaterial.
SELECT A.idMaterial, C.nombre_material, A.sum_qty_entrada, B.sum_qty_salida, (A.sum_qty_entrada - B.sum_qty_salida) total
FROM (
SELECT idMaterial, SUM(qty) sum_qty_entrada FROM mesa_entrada
GROUP BY idMaterial
)
AS A
JOIN (
SELECT idMaterial, SUM(qty) sum_qty_salida FROM mesa_salida
GROUP BY idMaterial
) AS B ON
A.idMaterial = B.idMaterial
JOIN mesa_con_nombre_material AS C ON
A.idMaterial = C.idMaterial
i think that you need this
SELECT SUM(hr) FROM
(
Select sum(qty) as hr FROM table1
UNION ALL
Select sum(qty) as hr FROM table2
)a
SELECT sum(amount) as amount , COUNT(userid) as total FROM table1 WHERE userid='1111' union all
SELECT sum(amount) as amount, COUNT(userid) as total FROM table2 WHERE userid='1111' union all
SELECT sum(amount) as amount, COUNT(userid) as total FROM table3 WHERE userid='1111' union all
SELECT sum(amount) as amount, COUNT(userid) as total FROM table4 WHERE userid='1111' union all
SELECT sum(amount) as amount, COUNT(userid) as total FROM table5 WHERE userid='1111'
I found this somewhere but its not working for me .
Proposed solution:
The other option is to get data from all tables separately and then display it .
Question:
I want to get data from multiple tables with single query. amount will be added and userid will be counted from all tables.
Additional Notes:
It should gather all the info about user id = 1111 and save in two varibables.
Userid= 1111 , may not be present in some tables.
Expect out will be like this:
your total : $total | and your amount : $amount
Based on suggestions. here is what i have acheieved so far and how i am trying to display it. it displays nothing without any errors:
If i use single query, then the results are displayed fine.
<?php
$sqltotal=mysql_query("SELECT SUM(data.Amount) as Amount ,SUM(data.total) as total
FROM
(
SELECT COALESCE(sum(amount),0) as amount , COALESCE(COUNT(userid)) as total FROM table1 WHERE userid='1111'
UNION ALL
SELECT COALESCE(sum(amount),0) as amount, COALESCE(COUNT(userid)) as total FROM table2 WHERE userid='1111'
UNION ALL
SELECT COALESCE(sum(amount),0) as amount, COALESCE(COUNT(userid)) as total FROM table3 WHERE userid='1111'
UNION ALL
SELECT COALESCE(sum(amount),0) as amount, COALESCE(COUNT(userid)) as total FROM table4 WHERE userid='1111'
UNION ALL
SELECT COALESCE(sum(amount),0) as amount, COALESCE(COUNT(userid)) as total FROM table5 WHERE userid='1111'
) as data
");
while($row = mysql_fetch_array($sqltotal))
{
echo "$row[total]";
echo "$row[sum]";
}
//echo "$yourtotal: $row[total]";
?>
If you need the single row for all the tables sum for the column amount then just do the Outer select on UNION. Now as you mentioned in comment may be some of tables may not contain the UserID you need to use the COALESCE to make sure that if null then get the 0 as selected value.
SELECT SUM(COALESCE(data.Amount,0)) as Amount ,SUM(COALESCE(data.total,0)) as total
FROM
(
SELECT COALESCE(sum(amount),0) as amount , COALESCE(COUNT(userid)) as total FROM table1 WHERE userid='1111'
UNION ALL
SELECT COALESCE(sum(amount),0) as amount, COALESCE(COUNT(userid)) as total FROM table2 WHERE userid='1111'
UNION ALL
SELECT COALESCE(sum(amount),0) as amount, COALESCE(COUNT(userid)) as total FROM table3 WHERE userid='1111'
UNION ALL
SELECT COALESCE(sum(amount),0) as amount, COALESCE(COUNT(userid)) as total FROM table4 WHERE userid='1111'
UNION ALL
SELECT COALESCE(sum(amount),0) as amount, COALESCE(COUNT(userid)) as total FROM table5 WHERE userid='1111'
) as data
And if you want to use the join then you need to use the LEFT JOIN and also need to do the SUM separately for each table and then add that to the main total.
SELECT sum(amount) as amount , COUNT(userid) as total FROM table1
Group By userid
Try this:
SELECT sum(table1.amount + table2.amount + table3.amount + table4.amount) as amount, COUNT(table1.userid) + COUNT(table2.userid) + COUNT(table3.userid) + COUNT(table4.userid) as total
FROM table1, table2, table3, table4
WHERE table1.userid='1111' OR table2.userid='1111' OR table3.userid='1111' OR table4.userid='1111'
i am seeking help on a query which shows movement of a stock item for a particular itemid.
Table1 Name: saleitems Fields: itemid, saledate, qty
Table2 Name: purchaseitems Fields: itemid, purchasedate, qty
Table3 Name: stocktransfers Fields: itemid, trfdate, from, to, qty
I want to pull out mysql data from all three tables and sort them based in the date fields. Any help is much appreciated.
The expected output should look like below
select * from saleitems,purchaseitems,stocktransfers
where your condition order by saledate,purchasedate,trfdate
you can use order by clause as given select whichever fields you want based on condition or join as per your logic and use order by
Try this:
(select itemid, "SALES" as type, saledate as dt, qty from salesitems)
union
(select itemid, "PURCHASE" as type, purchasedate as dt, qty from purchaseitems)
union
(select itemid, "STOCKTRANSFER" as type, trfdate as dt, qty from stocktransferitems)
order by dt;
I hope, I got your question right.
Hope this helps
select * from salesitems a
inner join purchaseitems b on a.itemid=b.itemid
inner join stocktransfer c on a.item_id=c.item_id
order by a.saledate,b.purchasedate,c.trfdate
SELECT a.itemid,a.saledate,a.qty,b.purchasedate,b.qty,c.trfdate,c.from,c.to,c.qty
FROM saleitems a INNER JOIN purchaseitems b
ON a.itemid = b.itemid
INNER JOIN stocktransfers c
ON a.itemid = b.itemid
WHERE a.itemid = 10
ORDER BY a.saledate , b.purchasedate , c.trfdate