Joining multiple MySQL Tables with one relations ID - mysql

I have 4 MySQL tables on identity column is in common between all these tables,
Tables in Sequence:
1- Items.
2- Sales.
3- Puchases.
4- Returned.
ItemID appears in all of these tables, WHEN i use LEFT JOIN i get duplicates like:
select
a.ItemID AS ItemID,
a.Item_title AS ItemTitle,
SUM(b.qty) AS SoldQty,
SUM(c.qty) AS PurQty,
SUM(d.qty) AS RetQty
from items a
left join sales b on a.ItemID = b.items_ItemID
left join purchases c on a.ItemID = c.items_itemID
left join returned d on a.ItemID = d.items_ItemID
group by a.ItemID
That query was one of the many tries that i've tried :D the result i get is always unique for sales but duplicates for other tables ..
Thanks for the answer.

If I understand what you're trying to do correctly, you want the total number of sales, purchases, returned etc per item id from a. If that's the case, try thinking about an easier piece of the problem first: how do I get the sum of each sales quantity, grouped by item id?
To do that you'd do something like:
select b.items_ItemID, sum(b.qty) as total_sales_qty
from sales b group by b.items_ItemID
You could do the same thing for tables c and d.
Once you've got those, you can join them all together like this:
select a.ItemID, bb.total_sales_qty, cc.total_purchases_qty, dd.total_returned_qty
from items a
left join (
select b.items_ItemID, sum(b.qty) as total_sales_qty
from sales b group by b.items_ItemID) bb
on a.ItemID = bb.items_ItemID
left join (
select c... etc) cc
on a.ItemID = cc.items_ItemID
... etc

I don't really use MySQL, but in SQL Server, you could use the distinct directive, so duplicate rows appear as just a single row. All the returned columns must be identical, mind you.
Select Distinct a.ItemID AS ItemID,... From....
Hope this helps

Related

how to merge 2 related tables even foreign key is null in MySQL? [duplicate]

I have two tables, like so:
table "a" contains:
id|name
stock1|fullname
stock2|fullname2
stock3|fullname3
table "b" contains product quantities for given stock.
id|stock_id|quantity|product_id|
1|stock1|3|13
2|stock3|4|13
3|stock1|1|5
4|stock2|2|2
Now I would need to combine those two tables, so that each product takes its stock full name from table "a", and if its quanitity is not given for stock, it would still show the row with the quanitity as 0.
So from my example, product_id 13 would show as:
stock|quanitity|product_id|stock_fullname
stock1|3|13|fullname1
stock2|0|13|fullname2
stock3|4|13|fullname3
You should be able to use a LEFT JOIN to achieve this.
SELECT a.id AS stock, COALESCE(b.quanitity,0), b.product_id, a.name AS stock_fullname
FROM a
LEFT JOIN b
ON a.id = b.stock_id
AND b.product_id = 13
It sounds like you need to use a LEFT JOIN, although the records with no quantity might show as NULL rather than zero. Something like:
SELECT a.*, b.*
FROM table_a a
LEFT JOIN table_b b ON a.stock_id = b.stock_id
try this:
SELECT stock,COALESCE(quanitity,0),product_id,stock_fullname FROM stock JOIN product
You need an outer join so that rows from the a table without a corresponding row in b are still considered. An inner join, by contrast, insists that you have a matching row. If you are pulling a value from the table where you don't have a row, you get NULL. Syntax varies between DBs and there is a distinction made depending on if it's the table on the left or right that gets the fake rows.
see other answers for syntax.
I think this query should work for your example:
SELECT a.id stock if(b.quantity IS NULL, 0, b.quantity),
b.product_id, a.name stock_fullname
FROM b
LEFT JOIN a b.stock = a.id
WHERE b.product_id = 13;
You should be able to use a LEFT JOIN to achieve this.
SELECT a.id AS stock, COALESCE(b.quanitity,0), b.product_id, a.name AS stock_fullname
FROM a
LEFT JOIN b
ON a.id = b.stock_id
AND b.product_id = 13

Check to see if the primary key exists in other multiple tables in mysql [duplicate]

I have two tables, like so:
table "a" contains:
id|name
stock1|fullname
stock2|fullname2
stock3|fullname3
table "b" contains product quantities for given stock.
id|stock_id|quantity|product_id|
1|stock1|3|13
2|stock3|4|13
3|stock1|1|5
4|stock2|2|2
Now I would need to combine those two tables, so that each product takes its stock full name from table "a", and if its quanitity is not given for stock, it would still show the row with the quanitity as 0.
So from my example, product_id 13 would show as:
stock|quanitity|product_id|stock_fullname
stock1|3|13|fullname1
stock2|0|13|fullname2
stock3|4|13|fullname3
You should be able to use a LEFT JOIN to achieve this.
SELECT a.id AS stock, COALESCE(b.quanitity,0), b.product_id, a.name AS stock_fullname
FROM a
LEFT JOIN b
ON a.id = b.stock_id
AND b.product_id = 13
It sounds like you need to use a LEFT JOIN, although the records with no quantity might show as NULL rather than zero. Something like:
SELECT a.*, b.*
FROM table_a a
LEFT JOIN table_b b ON a.stock_id = b.stock_id
try this:
SELECT stock,COALESCE(quanitity,0),product_id,stock_fullname FROM stock JOIN product
You need an outer join so that rows from the a table without a corresponding row in b are still considered. An inner join, by contrast, insists that you have a matching row. If you are pulling a value from the table where you don't have a row, you get NULL. Syntax varies between DBs and there is a distinction made depending on if it's the table on the left or right that gets the fake rows.
see other answers for syntax.
I think this query should work for your example:
SELECT a.id stock if(b.quantity IS NULL, 0, b.quantity),
b.product_id, a.name stock_fullname
FROM b
LEFT JOIN a b.stock = a.id
WHERE b.product_id = 13;
You should be able to use a LEFT JOIN to achieve this.
SELECT a.id AS stock, COALESCE(b.quanitity,0), b.product_id, a.name AS stock_fullname
FROM a
LEFT JOIN b
ON a.id = b.stock_id
AND b.product_id = 13

MySQL how to do permutation within one column and run a calculation?

Say I have a following table:
table1
Now I want to have a permutation within cid column for each two ids (lets say id1=A and id2=B), and try to calculate the intersection of pid of A and B divided by the union of pid of A and B. For example, let A = cid 1 and B = cid 2, then the answer is intersection/union = 0/(1+1)=0 (notice B has purchased pid 3 for three times, but same product count only once).
The result should be like:
result
There is going to be a permutation of any 2 different numbers in table1.cid, where smaller number goes before larger number, as well as the result of intersection/union. How can I write a query to perfome that?
Both union and intersection can be achieved by joining the table with itself on the PID column:
SELECT a.cid a, b.cid b, COUNT(*) intersection
FROM table a
INNER JOIN table b
ON a.pid = b.pid AND a.cid < b.cid
if you use an OUTER join, that count(*) will return the size of the union.
you can execute both queries, then join on CIDs to have both intersection and union available for the computation:
SELECT a, b, intersection/union
FROM (<intersection query>) i
JOIN (<union query>) u
ON i.a = u.a AND i.b = u.b
You could of course optimize this a little bit since the inner join is a subset of the outer join, so there's no real need to perform both, but that's a matter for another question...

MySQL nested selection

I am trying to figure out this question on a practice page online with the following tables:
Question:
For all cases in which the same customer rated the same product
more than once, and in some point in time gave it a lower rating
than before, return the customer name, the name of the product,
and the lowest star rating that was given.
I cant seem to figure out why this isnt correct - would anyone be able to help?
Here is what I have so far (without sample data):
SELECT
Customer.customer_name,
Product.product_name,
MIN(Rating.rating_stars)
FROM Rating
JOIN Product ON Rating.prod_id = Product.prod_id
JOIN Customer ON Rating.cust_id = Customer.prod_id
GROUP BY Customer.customer_name, Product.product_name
HAVING COUNT(Product.prod_id) > 1
This query will return the minimum rating stars of a product that has been reviewed more than once by the same customer, with any of the newer ratings lower than an older rating:
SELECT
r1.prod_id,
r1.cust_id,
MIN(r1.rating_star) AS min_rating
FROM
rating r1 INNER JOIN rating r2
ON r1.prod_id=r2.prod_id
AND r1.cust_id=r2.cust_id
AND r1.rating_date>r2.rating_date
AND r1.rating_star<r2.rating_star
GROUP BY
r1.prod_id,
r1.cust_id
you can then join this query with products and customers table:
SELECT
customer.customer_name,
product.product_name,
m.min_rating
FROM (
SELECT
r1.prod_id,
r1.cust_id,
MIN(r1.rating_star) AS min_rating
FROM
rating r1 INNER JOIN rating r2
ON r1.prod_id=r2.prod_id
AND r1.cust_id=r2.cust_id
AND r1.rating_date>r2.rating_date
AND r1.rating_star<r2.rating_star
GROUP BY
r1.prod_id,
r1.cust_id) m
INNER JOIN customer on m.cust_id = customer.cust_id
INNER JOIN product ON m.product_id = product.product_id
Just a few points:
You cant specify the tables in the FROM clause the sane way you specify attributes in the SELECT. You can only have a single table in the FROM, and one more for each Join you use.
SELECT a, b, c FROM a; <----------fine
SELECT a, b, c FROM a, b; <----not fine
SELECT a, b, c FROM a JOIN b; <---fine
When it comes to the tables in the FROM/JOIN, you dont use "AS" to give them an alias, just the table name followed by the alias.
FROM atable a JOIN btable b; <--This assigns alias a to "atable" and b to "btable".
You also have to specify the common attribute that the tables are going to be joined on:
customer JOIN rating ON customer.cust_id = rating.cust_id;
As for the rest you can probably work out the correct WHERE clauses to use once you have the syntax down.

mysql join 2 tables - show all rows from one table

I have two tables, like so:
table "a" contains:
id|name
stock1|fullname
stock2|fullname2
stock3|fullname3
table "b" contains product quantities for given stock.
id|stock_id|quantity|product_id|
1|stock1|3|13
2|stock3|4|13
3|stock1|1|5
4|stock2|2|2
Now I would need to combine those two tables, so that each product takes its stock full name from table "a", and if its quanitity is not given for stock, it would still show the row with the quanitity as 0.
So from my example, product_id 13 would show as:
stock|quanitity|product_id|stock_fullname
stock1|3|13|fullname1
stock2|0|13|fullname2
stock3|4|13|fullname3
You should be able to use a LEFT JOIN to achieve this.
SELECT a.id AS stock, COALESCE(b.quanitity,0), b.product_id, a.name AS stock_fullname
FROM a
LEFT JOIN b
ON a.id = b.stock_id
AND b.product_id = 13
It sounds like you need to use a LEFT JOIN, although the records with no quantity might show as NULL rather than zero. Something like:
SELECT a.*, b.*
FROM table_a a
LEFT JOIN table_b b ON a.stock_id = b.stock_id
try this:
SELECT stock,COALESCE(quanitity,0),product_id,stock_fullname FROM stock JOIN product
You need an outer join so that rows from the a table without a corresponding row in b are still considered. An inner join, by contrast, insists that you have a matching row. If you are pulling a value from the table where you don't have a row, you get NULL. Syntax varies between DBs and there is a distinction made depending on if it's the table on the left or right that gets the fake rows.
see other answers for syntax.
I think this query should work for your example:
SELECT a.id stock if(b.quantity IS NULL, 0, b.quantity),
b.product_id, a.name stock_fullname
FROM b
LEFT JOIN a b.stock = a.id
WHERE b.product_id = 13;
You should be able to use a LEFT JOIN to achieve this.
SELECT a.id AS stock, COALESCE(b.quanitity,0), b.product_id, a.name AS stock_fullname
FROM a
LEFT JOIN b
ON a.id = b.stock_id
AND b.product_id = 13