MySQL join table return only one match - mysql

I'm struggling the the JOIN in a MySQL query. Somehow I can't find out why my result is not what I want.
I have two tables, a table orders and a table products. The table product holds the order.id of the order. So a order can have more than one products, so for example the table products holds two records for a order.
The result I need is all orders where a product holds a VAT of 21.
Table example.
orders
id | customer
---------------
1 | John Doe
2 | Hello World
order_products
id | order_id | product | vat
1 | 1 | Porsche 911 GT4 | 21
2 | 1 | Audi R8 LMS | 21
3 | 1 | Ferrari Enzo | 19
3 | 2 | Bugatti Veyron | 19
No I want all orders where the products have a VAT of 21. So I will do a LEFT JOIN on the table order_products:
SELECT orders.id, orders.customer, order_products.product FROM orders LEFT JOIN order_products ON orders.id = order_products.order_id WHERE order_products.vat = '21'
This returns the following:
1 John Doe Porsche
1 John Doe Audi R8 LMS
But I only need one result because the orders.id is important for me, not all products in the order. I only join on the order_products to get the orders with only VAT 21. At the moment I ran out of options on how to fix this. Even after reading several topics about joins on this site and other sites.

First, you aren't going to return any orders that don't have products, so there is no need for a left join...an inner join is fine.
If the orders_product is not important to you, you can use a subquery and not select any columns from the orders_product. With your current query, you're selecting a column though.
Something like...
SELECT id, customer
FROM orders
WHERE order_id IN (SELECT order_id FROM order_products
WHERE order_products.vat = '21');
If you prefer not to use a correlated subquery, you can use a group by or distinct
SELECT orders.id, orders.customer
FROM orders
INNER JOIN order_products ON orders.id = order_products.order_id
WHERE order_products.vat = '21'
GROUP BY orders.id, orders.customer;
or...
SELECT DISTINCT orders.id, orders.customer
FROM orders
INNER JOIN order_products ON orders.id = order_products.order_id
WHERE order_products.vat = '21';

If you only care about the orders then you can group by the order id:
SELECT orders.id, orders.customer, order_products.product
FROM orders
LEFT JOIN order_products ON orders.id = order_products.order_id
WHERE order_products.vat = '21'
GROUP BY orders.id;
However note that order_products.product will only be one of the products. If you wish to display all of the products but in the one column you can user GROUP_CONCAT:
SELECT orders.id, orders.customer, GROUP_CONCAT(order_products.product)
FROM orders
LEFT JOIN order_products ON orders.id = order_products.order_id
WHERE order_products.vat = '21'
GROUP BY orders.id;
This will return:
1 John Doe Porsche, Audi R8 LMS

SELECT DISTINCT o.id
, o.customer
FROM orders o
JOIN order_products op
ON op.order_id = o.id
WHERE op.vat = 21;

Related

MySQL Join or Subquery

I need a mysql query for all products last purchased date. My mind has gone blank around joins and subqueries.
3 tables - products (need all records), orders (order header info with date) and order_products which has the product detail lines for the order header.
orders_products has key products_id links to products table
orders_products has key order_id that links to orders table
Data similar to
products
product_id
----------
apples
bananas
pears
orders
orders_id date_purchased
------------------------------
1 2018-06-24 12:37:42
2 2020-10-27 10:30:00
3 2019-08-25 16:43:36
orders_products
orders_id products_id
---------------------
1 apples
1 pears
2 bananas
2 pears
2 apples
3 bananas
3 apples
A pseudo query would look like
for each product
find last order where order.products.products_id = products.products_id by order.date_purchased desc limit 1
The result needed
Product_id | Date_last_purchased
Try next query:
SELECT
p.products_id,
coalesce(MAX(date_purchased), 'never purchased') last_purchased
FROM products p
LEFT JOIN orders_products op on p.products_id = op.products_id
LEFT JOIN orders o ON o.orders_id = op.orders_id
GROUP BY products_id;
Test query on SQLize.online
As far as I understand, this is what you need.
SELECT p.product_id, o.date_purchased
FROM products p
LEFT JOIN orders_products op ON op.products_id = p.product_id
LEFT JOIN orders o ON o.orders_id = op.orders_id
GROUP BY op.products_id
ORDER BY o.date_purchased DESC

Mysql query with count(distinct) show nothing if group by has no result

I have a query on 3 tables, settlement, order and passenger.
A settlement has orders, and orders has passengers.
TABLE: Settlemnt
id
TABLE: Order
id settlement_id
TABLE: passenger
id orders_id
If settlement has no orders (and then no passengers), it returns nothing.
What I want, is to return the empty settlement even if it has no orders.
It is the count(passengers) that ruins it for me and returns no settlement if empty.
This is the simplified query:
select s.id, o.id, count(distinct p.id)
from settlement s
left join orders o ON o.settlement_id = s.id
left join passenger p on p.orders_id = o.id
where s.date = '2016-02-02';
group by o.id
How can I make it return settlements with no orders?
Works for me...
SELECT s.id s_id
, o.id o_id
, p.id p_id
FROM settlement s
LEFT
JOIN orders o
ON o.sid = s.id
LEFT
JOIN passengers p
ON p.oid = o.id;
+------+------+------+
| s_id | o_id | p_id |
+------+------+------+
| 1 | NULL | NULL |
| 2 | 1 | 1 |
+------+------+------+
http://sqlfiddle.com/#!9/9a01b/4
The major problem with your query appears to be that you GROUP BY the o.id. Any settlement that has no order will have an o.id of NULL, hence all settlements with no orders will be lumped together into one row. Which s.id that is returned for this o.id is not defined (and effectively random).
Change it to GROUP BY both s.id and o.id
SELECT s.id,
o.id,
COUNT(DISTINCT p.id)
FROM settlement s
LEFT JOIN orders o ON o.settlement_id = s.id
LEFT JOIN passenger p ON p.orders_id = o.id
WHERE s.date = '2016-02-02';
GROUP BY s.id,
o.id

How to get all potential orders from a mysql table

I have a mysql query and can't quite figure out how to pull up all potential customers for a certain product_id from a given country_id. I want a result that has just one record per customer.
My tables are orders and customers.
---customers--
customer_id
country_id
name
---orders---
order_id
product_id
customer_id
My current query below gives too many results. Namely records from other product_id's that are not = 1. Here is my query:
SELECT o.order_id
, c.name
, c.customer_id
, c.country_id
, o.product_id
FROM customers c
LEFT
JOIN orders o
ON o.customer_id = c.customer_id
WHERE o.product_id = 1
OR c.country_id = 1
Some sample results might look like this:
order_id name customer_id country_id product_id
1 Joe Smith 1 1 1
2 Joe Smith 1 1 2
3 John Doe 2 1 1
4 Kirk Smith 3 1 1
NULL Ron Rhoden 6 1 1
NULL Sam Smith 7 1 1
For my purposes you can assume that a given customer will only order a given product once. Notice how I get a result for Joe Smith with product_id=2. I don't want that result in my list. The Ron Rhoden and Sam Smith results are desirable for my purposes. How do I filter the product_id<>1 records but still include all the country_id=1 records?
Thanks.
This is my attempt:
SELECT o.order_id
, c.name
, c.customer_id
, c.country_id
, o.product_id
FROM customers c
LEFT
JOIN orders o ON o.customer_id = c.customer_id
WHERE o.order_id IN (SELECT order_id FROM orders WHERE product_id = 1)
OR c.country_id IN (SELECT customers.country_id FROM customers WHERE product_id = 1)
);
If I understand correctly, you want all customers from country "1" that have ordered product "1". I would suggest using exists:
select c.*
from customers c
where c.country_id = 1 and
exists (select 1
from orders o
where o.customer_id = c.customer_id and
o.product_id = 1
);
Ok, I think this works. A bit complicated but I first asked for all the product_id=1 records from orders then did a UNION query and then asked for everyone in customers with country_id=1 but NOT IN the previous product_id=1 results.
SELECT o.order_id, c.name, c.customer_id, c.country_id, o.product_id
FROM customers c LEFT JOIN orders o ON o.customer_id = c.customer_id
WHERE o.product_id = 1 UNION SELECT NULL AS order_id, c.name, c.customer_id, c.country_id, NULL AS product_id
FROM customers c
WHERE c.country_id = 1 AND c.customer_id NOT IN (SELECT c2.customer_id FROM customers c2 INNER JOIN orders o2 ON c2.customer_id=o2.customer_id WHERE o2.product_id=1)

MySQL query - Join Query

Not sure how to write this join for 2 tables. Here is some sample data to illustrate:
orders
-----------------------
| order_id | customer |
-----------------------
ABC12345 1
ABC12346 4
ABC12347 3
ABC12348 2
ABC12349 2
ABC12350 3
customers
-----------------------------------
| id | name | email |
-----------------------------------
1 James james#gmail.com
2 Alice alice#hotmail.com
3 Jimbo james#gmail.com
4 Jim james#gmail.com
5 Lucy lucy#yahoo.com
I have an order_id, which I already know. Let's use the first one in the table: ABC12345. As you can see, the customer ID is 1, so that order was placed by James. Now sometimes James has ordered again using different names but we know it's him because of his email address.
So how do I retrieve all of James' orders based on his email address of james#gmail.com, if I know one of his order numbers (ABC12345)?
Edit: Not sure I stressed this enough... James has ordered 3 times, using the same email address but names of James, Jim and Jimbo. I need all of his orders using james#gmail.com as the email address.
SELECT o2.order_id
FROM orders o1
INNER JOIN customers c1
ON o1.customer = c1.id -- get the customer for the first order
INNER JOIN customers c2
ON c1.email = c2.email -- find all customers with same email
INNER JOIN orders o2
ON c2.id = o2.customer -- find all orders for those customers
WHERE o1.order_id = 'ABC12345'
You can use this:
SELECT order_id
FROM orders
WHERE customer IN (
SELECT id
FROM customers
WHERE email = (SELECT c.email FROM customers c JOIN orders o ON c.id = o.customer WHERE o.order_id = 'ABC12345')
)
You need to first quantify the person of the order to the customer table... Then, get all customer IDs by that same email... THEN get the orders that qualify those customer IDs.
select o2.*
from orders o2
JOIN ( select c2.ID
from customers c2
join ( select c1.email
from orders o
join customers c1
on o.Customer = c1.ID
where
o.order_id = 'ABC12345' ) FoundTheEmail
on c2.email = FoundTheEmail.email
) as SameCustomerEMail
on o2.Customer = SameCustomerEMail.ID
SELECT order_id
FROM orders
WHERE customer IN (SELECT customer
FROM orders
WHERE order_id = 'ABC12345')
try this since james has only one order
SELECT orders.order_id, customers.name, customers.email
FROM orders
INNER JOIN customers ON customers.id = orders.customer
WHERE orders.orer_id = 'ABC12345'
The order ID is a UNIQUE number, then you will not have two orders with the same ID, why care about the customer name?
"Every order will have a Customer's ID."

mysql count, distinct, join? Confusion

i have 2 tables:
tblItems
ID | orderID | productID
1 1 2
2 1 2
3 2 1
4 3 2
tblProducts
productID | productName
1 ABC
2 DEF
im attempting to find the most popular Product based on whats in "tblItems", and display the product Name and the number of times it appears in the tblItems table.
i can get mysql to count up the total like:
$sql="SELECT COUNT(productID) AS CountProductID FROM tblItems";
but i can't figure out how to join the products table on..if i try LEFT JOIN the query goes horribly wrong
hopefully thats not too confusing..thankss
Are you simply trying to find the count of orders by product like so:
Select P.ProductName, Count(*)
From tblItems As I
Join tblProducts As P
On P.ProductId = I.ProductId
Group By P.ProductName
I think you may be looking for something like:
SELECT tblProducts.productName, COUNT(tblItems.ID)
FROM tblProducts
LEFT JOIN tblItems USING(productID)
GROUP BY tblProducts.productID
SELECT count(i.productID) AS cnt, p.productName FROM tblItems AS i
LEFT JOIN tblProducts AS p ON p.productID = i.productID
GROUP BY i.productID
ORDER BY cnt desc