Reputation: 53
I'm getting data about products from 3 different tables and I want to show only products the user didn't order.
Table 1:
Supplier
__________________
| id | name | .. |
|____|______|____|
| 1 | john | .. |
|____|______|____|
Table 2:
Product
___________________________
| id | p_name| supplier_id |
|____|_______|_____________|
| 1 | phone | 1 |
|____|_______|_____________|
| 2 | watch | 1 |
|____|_______|_____________|
Table 3:
Order
___________________________
| id | p_id | buyer_id |
|____|_______|_____________|
| 1 | 1 | 10 |
|____|_______|_____________|
So in this case when the user visit the products page, I want to show the products he didn't order which is watch
in this example.
My SQL query:
SELECT supplier.name, products.p_name FROM products
INNER JOIN supplier ON supplier.id = product.supplier_id
INNER JOIN order ON product.id = order.p_id
I tried LEFT JOIN order ON product.id != order.p_id
and WHERE order.p_id IS NULL
, But no success.
So how to check if the user didn't order this product? Then show the rest of the products?
Upvotes: 0
Views: 505
Reputation: 146460
It should be something like this:
SELECT supplier.name, products.p_name
FROM product
INNER JOIN supplier ON supplier.id = product.supplier_id
LEFT JOIN order ON product.id = order.p_id
WHERE order.id IS NULL
You issue a LEFT JOIN
against order
to also get products without a match and you discard rows without matches with order.id IS NULL
. There's also no need to discard duplicate rows because products that haven't been ordered will only appear once.
+---------+
| |
| |
| |
| product +--------+
| | |
| | order |
| | |
+---------+--------+
Upvotes: 1
Reputation:
This is an unusual schema; A supplier would not normally be an attribute of a 'products' table, and the details of the order would normally be held in a separate table from the orders - otherwise an order can only comprise one item, but anyway...
DROP TABLE IF EXISTS suppliers;
CREATE TABLE suppliers
(id INT AUTO_INCREMENT PRIMARY KEY
,name VARCHAR(12) UNIQUE
);
INSERT INTO suppliers VALUES
(1,'john');
DROP TABLE IF EXISTS products;
CREATE TABLE products
(id INT AUTO_INCREMENT PRIMARY KEY
,product_name VARCHAR(12) UNIQUE
,supplier_id INT NOT NULL
);
INSERT INTO products VALUES
(1,'phone',1),
(2,'watch',1);
DROP TABLE IF EXISTS orders;
CREATE TABLE orders
(id INT AUTO_INCREMENT PRIMARY KEY
,product_id INT NOT NULL
,buyer_id INT NOT NULL
);
INSERT INTO orders VALUES
(1,1,10);
...
SELECT p.*
FROM products p
LEFT
JOIN orders o
ON o.product_id = p.id
WHERE o.id IS NULL;
+----+--------------+-------------+
| id | product_name | supplier_id |
+----+--------------+-------------+
| 2 | watch | 1 |
+----+--------------+-------------+
Upvotes: 0
Reputation: 10163
You can use WHERE NOT EXISTS
statement for you case:
SELECT suppliers.name, products.name
FROM products
INNER JOIN suppliers ON suppliers.id = products.supplier_id
WHERE NOT EXISTS (
SELECT product_id FROM orders WHERE orders.product_id = products.id
);
Upvotes: 1
Reputation: 798
You can use a WHERE product NOT IN
to exclude specific products, shown below.
SELECT supplier.name, products.p_name
FROM products
INNER JOIN supplier ON supplier.id = products.supplier_id
WHERE products.id NOT IN (
SELECT p_id FROM order WHERE buyer_id = supplier.id
)
Within the WHERE
statement, you select the product id's of all the orders from a specific user. By applying NOT IN
all of these products will be excluded in your list.
Upvotes: 2