Joining 4 tables related - mysql

I'm trying to join these 4 tables:
customers:
id_customer;
name;
surname
employers:
id_employer;
id_customer;
products_to_employer
id_product;
id_employer;
products
id_product;
name_product;
code;
price;
Where i basically try to get all products of a customer. Basically each product is related whit a id_employer, but each employer is related whit a customer, so what i want is to bring all the products that is not related whit the employer but whit his "parent" the customer.
The result I want to get is:
Result:
Example: variable $id_customer: 4
products result:
id_customer (id nr 4)
name_product;
name_product;
code;
price;

This is the requirement:
Where i basically try to get all products of a customer
So it is just a matter of applying some joins and a where clause for the filter on id_customer
select p.* from products p
join products_to_employer pe on p.id_product = pe.id_product
join employers e on pe.id_employer = e.id_employer
join customers c on e.id_customer = c.id_customer
where c.id_customer = 4
NOTE: There shouldn't be any need of adding the id_customer to the results as you are already filtering by it.

select c.id_customer, c.name, p.name_product, p.code, p.price
from products p
inner join products_to_employer pte on (pte.id_product = p.id_product)
inner join employers e on (e.id_employer = pte.id_employer)
inner join customers c on (c.id_customer = e.id_customer)
where c.id_customer = 4

Related

Join 3 tables with MySQL

I have the following tables:
Products
prod_id | prod_name | prod_price
Supermarket
supermarket_id | name | address
supermarket_product
supermarket_id | product_id
How can I join those tables to get a table that shows all the information from Products and Supermarket tables in 1 single big table? I am basically trying to have a table only to hold which product belongs to which supermarket based on it.
I tried the following, but it doesn't work:
SELECT prod_name, prod_price, supermarkets.name
FROM products
INNER JOIN supermarkets
ON supermarket_product.supermarket_id = supermarket.supermarket_id;
You need to join products and supermarkets through bridge table supermarket_product:
select p.*, s.*
from products p
inner join supermarket_product sp on sp.product_id = p.prod_id
inner join supermarket s on s.supermarket_id = sp.supermarket_id
You need to also include supermarket_products in the query. You should also use table aliases to simplify your code:
SELECT p.prod_name, p.prod_price, s.name
FROM products p
INNER JOIN supermarket_product sp ON sp.product_id = p.prod_id
INNER JOIN supermarket s on s.supermarket_id = sp.supermarket_id

Joining three tables with parent-child relationship

Suppose that we have four tables in the following structure (Table name - fields):
person - id, name
doctor - id_person, specialty
pacient - id_person, disease
appointment - doctor_id, pacient_id, date
How can I construct a query to return the doctor's name and specialty, the pacient's name and disease and the appointment date?
Here's where I've got so far:
SELECT person.name, doctor.specialty, pacient.disease, appointment.date
FROM appointment
INNER JOIN person
ON appointment.pacient_id=person.id
INNER JOIN doctor
ON appointment.doctor_id=doctor.id_person
INNER JOIN pacient
ON appointment.pacient_id=pacient.id_person
But this is not returning the right fields. I think the problem resides in returning the same field (person.name) for two different ids (doctor and pacient) in the same row.
You need to do two separate joins to the person table, and use aliases to identify the individual tables like so:
select
dp.name as DoctorName
, doctor.specialty
, pp.name as PacientName
, pacient.disease
, appointment.date
from appointment
inner join doctor
on appointment.doctor_id = doctor.id_person
inner join person dp
on appointment.doctor_id = dp.id
inner join pacient
on appointment.pacient_id = pacient.id_person
inner join person pp
on appointment.pacient_id = pp.id

Getting data from multiple tables in sql

Table 1: Invoices (inv_id, inv_value, cust_id)
Table 2: Customers (cust_id, sales_rep)
Table 3: Members (Member_id, member_cateogry, member_type, cust_id)
Note 1: Each Customer Pays multiple Invoices. (One-to-Many Relationship).
Note 2: Each Customer pays for one-or-more members (so more than one member could be related to one customer).
Note 3: Each Member has a category which could be 1 "represents Individual" OR 2 "represents Group".
Note 4: Each Member has a type which could be 1 "represents new" OR 2 "represents renew".
I want to get the TOTAL of the Invoice_value field for customers who's sales_rep = 1 and their member_category = 10 and their members_type = 123
Ex: What is the total amount of Invoices that customers paid IF the Sales_rep for these customers was 1 and the members they paid for were new and Individual members.
I tried:
SELECT Sum(invoices.inv_value) AS total
FROM invoices,
customers,
members
WHERE invoices.cust_id = customers.cust_id
AND members.custid = customers.cust_id
AND members.category = {$category}
AND members_type = {$type}
AND customers.sales_rep = {$id}";
AND
SELECT Sum(invoices.inv_value) AS total
FROM members
INNER JOIN customers
ON members.custid = customers.cust_id
INNER JOIN invoices
ON customers.cust_id = invoices.cust_id
WHERE customers.sales_rep = {$id}
AND members.category = {$category}
AND members.type = {$type}";
But both return double the Invoice value.
ex.: 1 Invoice for $120 in the Invoices table return $240 using these sql queries.
How can I fix this?
This is your query:
SELECT sum(i.inv_value) as total
FROM members m INNER JOIN
customers c
ON m.custid = c.cust_id INNER JOIN
invoices i
ON c.cust_id = i.cust_id
WHERE c.sales_rep = {$id} AND
m.category = {$category} AND
m.type = {$type}";
(Don't use implicit JOIN syntax using commas. It is archaic and less powerful.)
The problem is probably that two members can have the same customer id. You can check this by running:
select m.cust_id, count(*)
from members m
group by m.cust_id
having count(*) > 1;
It is also possible that customer ids are duplicated in customers.
Assuming the duplicates are only in members, change the query to exists:
SELECT sum(i.inv_value) as total
FROM customers c
ON INNER JOIN
invoices i
ON c.cust_id = i.cust_id
WHERE c.sales_rep = {$id} AND
EXISTS (SELECT 1
FROM members m
WHERE m.custid = c.cust_id AND
m.category = {$category} AND
m.type = {$type}
);
It seems like you are taking inv_value from invoices, which has many to one relationship with customers but customer table and members table have one to many relationship.
Say you have below data
Invoice Table
invoices.cust_id invoices.inv_value
custid1 100
Customer table
customer.cust_id
custid1
Members Table
members.cust_id members.category
custid1 1
custid1 2
On join all three tables
customer.cust_id members.cust_id invoices.inv_value members.category
custid1 custid1 100 1
custid1 custid1 100 2
if you notice as custid1 exist in 2 member_category, invoice value is also duplicated.
To solve this, first you can take the distinct records, then summing those distinct records would help you solve your problem as below
Solution
SELECT Sum(invoices.inv_value) AS total
FROM(
SELECT DISTINCT members.custid, invoices.inv_value inv_value
FROM members
INNER JOIN customers
ON members.custid = customers.cust_id
INNER JOIN invoices
ON customers.cust_id = invoices.cust_id
WHERE customers.sales_rep = {$id}
AND members.category = {$category}
AND members.type = {$type});

WHERE value IS NOT IN (subquery)

I've been struggling with this query.
I have two tables. One with coupons and Invoicenumbers. One with Invoicenumbers and customer names.
I need to get the customers who have not used a given coupon.
Here are the tables:
Promotion table:
Promotions
Invoice | Coupon
----------------
1 | couponA
2 | couponB
3 | couponB
Orders Table:
Orders
Invoice | Customer
------------------
1 | Jack
2 | Jack
3 | Jill
So Jack has used coupons A and B. And Jill has only used coupon B.
If my query were select customers who have not used coupon A, I should get Jill.
This works, but it seems clumsy and slow. Is there a better way?
SELECT Customer
FROM Promotions INNER JOIN Orders
ON Promotions.Invoice = Orders.Invoice
WHERE Customer NOT IN(
SELECT Customer
FROM Promotions INNER JOIN Orders
ON Promotions.Invoice = Orders.Invoice
WHERE Coupon = couponA)
GROUP BY Customer
Thanks for looking!
edit:
Here's an SQLFiddle schema
http://sqlfiddle.com/#!2/21d31/6
Updated: We should use prefer to use joins for better performance when its easy to do for us. Join vs. sub-query
Sql Fiddle
Select distinct Customer from orders o
join
(
SELECT distinct Customer as changedname FROM Orders o2
join
(
Select distinct invoice from Promotions where Coupon='couponA'
) t3
on o2.invoice = t3.invoice
) t2
on o.customer != t2.changedname;
Note: I changed column name customer for t3 because two joined tables must have different column names
Explanation:
Using inner or sub query is expensive when you have big data. use joins instead, lets learn converting subquery to join
With Subquery We had:
Select distinct Customer from orders where customer not in
(SELECT distinct Customer FROM Orders where invoice in
(Select distinct invoice from Promotions where Coupon='couponA'));
Converting sub-query to join
First step:
Select distinct Customer from orders o
join
(
SELECT distinct Customer as changedname FROM Orders where invoice in
(Select distinct invoice from Promotions where Coupon='couponA')
) t2
on o.customer != t2.changedname;
2nd step:
Select distinct Customer from orders o
join
(
SELECT distinct Customer as changedname FROM Orders o2 where invoice
join
(
Select distinct invoice from Promotions where Coupon='couponA'
) t3
on o2.invoice = t3.invoice
) t2
on o.customer != t2.changedname;
And that's it, much faster for tables having numerous rows
Original answer:
Use not in. Have a look.
Select distinct Customer from orders where customer not in
(SELECT distinct Customer FROM Orders where invoice in
(Select distinct invoice from Promotions where Coupon='couponA'));
Edit I have added distinct to make query faster
SQL Fiddle
SELECT DISTINCT o2.customer FROM ORDER o2
LEFT JOIN (promotions p1
JOIN Orders o1 ON p1.cuopon = 'CuoponA' AND p1.invoice = o1.invoice ) p3
ON o2.customer = p3.customer
WHERE p3.customer IS NULL
Try this query instead:
SELECT DISTINCT Customer
FROM Orders o1
WHERE NOT EXISTS (
SELECT 1
FROM Orders o2
INNER JOIN Promotions ON Promotions.Invoice = o2.Invoice
WHERE o1.Customer = o2.Customer AND Coupon = 'couponB')
The idea is to get rid of the GROUP BY by removing a join in the top part of the query, and also eliminate the NOT IN by making a coordinated subquery.
Here is a link to sqlfiddle.
Try this with a right join
SELECT Customer, Coupon
FROM Promotions
RIGHT JOIN Orders ON Promotions.Invoice = Orders.Invoice
AND Coupon = 'couponA'
GROUP BY Customer
HAVING Coupon IS NULL

Select Rows From Second Table Based On id From First

I have 2 tables
1_products
id, code, make, model, fk_group_id
1_stock
id, stock, repair
I want to be able to return all of the rows in both tables based on the match in the first. Say WHERE fk_group_id = 11
Here is one:
SELECT *
FROM products AS p
INNER JOIN stock AS s ON p.id = s.id
WHERE fk_group_id = 11