Inner join, sql confused - mysql

This is the challeng for my class.
Using INNER JOIN retrieve the following information:
Using the customers and orders table find all the orders that were created by an owner of a company.
I came up with this but when I enter it it says empty set>>>
SELECT id FROM orders INNER JOIN customers USING (id);
These are the columns from the customers table.
CUSTOMERS
| id | company | last_name | first_name | email_address | job_title
| business_phone | home_phone | mobile_phone | fax_number | address
| city | state_province | zip_postal_code | country_region | web_page
| notes | attachments |.
These are the columns from the orders table.
ORDERS
| id | employee_id | customer_id | order_date | shipped_date | shipper_id
| ship_name | ship_address | ship_city | ship_state_province
| ship_zip_postal_code | ship_country_region | shipping_fee | taxes
| payment_type | paid_date | notes | tax_rate | tax_status_id | status_id

When you write:
SELECT id FROM orders INNER JOIN customers USING (id);
you are requesting:
SELECT o.ID -- or c.ID
FROM Orders AS o
JOIN Customers AS c
ON O.ID = C.ID;
You're asking "which customers have an ID that is the same as an order ID?", which is probably not what you meant.
Most likely, you want to use some variant of:
SELECT o.ID AS Order_ID, c.ID AS Customer_ID
FROM Orders AS o
JOIN Customers AS c
ON O.Customer_ID = C.ID;
You get to choose what information you get in the select list.

You can find examples of inner join syntax here. Here is one example of how to do this:
select o.*
from orders o
inner join customers c on o.customer_id = c.id
/* not sure how "owner of company" is represented in the data, but I'm assuming it's some value for job_title */
where c.job_title = 'owner'

Related

How do I join multiple (four) tables using sql with conditions?

I am trying to create an SQL query that conditionally pulls data from multiple tables.
I have four tables:
orders
+------+------------+------------+
| id | date_added | currency |
+------+------------+------------+
| 1 | 2018-07-23 | 1 |
+------+------------+------------+
order_items
+------+------------+------------+---------------+---------------+
| id | order_id | price | product_id | product_type |
+------+------------+------------+---------------+---------------+
| 1 | 1 | 100.00 | 1 | ticket |
+------+------------+------------+---------------+---------------+
order_data
+------+--------------+---------------+
| id | order_id | ext_order_ref |
+------+--------------+---------------+
| 1 | 1 | ABC |
+------+--------------+---------------+
products
+------+------------+------------+
| id | date | product_id |
+------+------------+------------+
| 1 | 2020-03-12 | 1 |
+------+------------+------------+
| 2 | 2020-03-18 | 2 |
+------+------------+------------+
| 3 | 2020-03-20 | 3 |
+------+------------+------------+
I need to output orders with the following conditions:
Each order in a row with total (calculated from order items with matching order id)
The 'ext_order_ref' from the order_data table that matches that order
Only include order items that have a specific product type
Only include orders with products from a particular date range
Preferred output would look like this:
+------------+------------+--------------+
| order_id | total | ext_order_ref|
+------------+------------+--------------+
| 1 | 100 | ABC |
+------------+------------+--------------+
My current query is basically like this; please advise
SELECT
orders.id as order_id,
SUM(order_items.price) as total,
order_data.ext_order_ref
FROM orders
INNER JOIN order_data
ON orders.id = order_data.ext_order_ref
RIGHT JOIN order_items
ON orders.id = order_items.order_id
LEFT JOIN products
ON order_items.product_id = products.product_id
WHERE order_items.product_type = 'ticket' AND products.date BETWEEN '2020-03-12' AND '2020-03-18'
GROUP BY orders.id
It almost works, but not quite. The date particularly is causing issue.
Thanks in advance!
First decide the driving table for the query and form the query based on the driving table.
Driving table is the one primary table from which other tables join.
More information on driving tables from askTom
In your case, the driving table is Orders table. You are switching between RIGHT OUTER JOIN and LEFT OUTER JOIN. This will cause confusion in the resultset.
I have modified the query. See whether it works.
SELECT
orders.id as order_id,
SUM(order_items.price) as total,
order_data.ext_order_id
FROM orders
INNER JOIN order_data
ON orders.id = order_data.ext_order_id
LEFT OUTER JOIN order_items
ON orders.id = order_items.order_id
LEFT OUTER JOIN products
ON order_items.product_id = products.product_id
WHERE order_items.product_type = 'ticket' AND products.date BETWEEN '2020-03-12' AND '2020-03-18'
GROUP BY orders.id
I don't understand why you would want outer joins at all. If I follow the conditions correctly:
SELECT o.id as order_id,
SUM(oi.price) as total,
od.ext_order_id
FROM orders o INNER JOIN
order_data od
ON o.id = od.ext_order_id INNER JOIN
order_items oi
ON o.id = oi.order_id INNER JOIN
products p
ON oi.product_id = p.product_id
WHERE oi.product_type = 'ticket' AND
p.date >= '2020-03-12' AND
p.date < '2020-03-19'
GROUP BY o.id, od.ext_order_id;
Note the use of table aliases so the query is easier to write and read.

MySql query code to fetch unique data from single ID

How do i List the CUSTNUMs and NAMES of any customer who has only ordered chemical [NUMBER].
ORDERS TABLE
+---------+--------+------------+------+
| CUSTNUM | CHEMNO | DATE | QTY |
+---------+--------+------------+------+
| 123456 | 1234 | 2000-00-00 | 35 |
+---------+--------+------------+------+
CUSTOMER TABLE
+---------+-----------+-----------+
| CUSTNUM | NAME | LOCATION |
+---------+-----------+-----------+
| 123456 | AmChem | New York |
+---------+-----------+-----------+
You could join the CUSTOMER and ORDERS tables containing orders for a particular <chemno> with a subquery for the custnum that buy only a product:
SELECT
CUSTNUM, NAME
FROM
CUSTOMER c
INNER JOIN
ORDERS o ON o.CUSTNUM = c.CUSTNUM and o.CHEMNO = <chemno>
INNER JOIN
( SELECT
CUSTNUM
FROM
ORDERS
GROUP BY
CUSTNUM
HAVING
COUNT(DISTINCT CHEMNO) = 1 ) t ON t.CUSTNUM = o.CUSTNUM
I will approach this with one join between both tables, then grouping by the column CUSTNUM of the ORDERS table and finally adding the required conditions on the HAVING clause, like this:
SELECT
o.CUSTNUM,
c.NAME
FROM
ORDERS AS o
INNER JOIN
CUSTOMER AS c ON c.CUSTNUM = o.CUSTNUM
GROUP BY
o.CUSTNUM
HAVING
( COUNT(DISTINCT o.CHEMNO) = 1 AND MIN(o.CHEMNO) = <some_chemno> )
OK, slow day...
SELECT DISTINCT x.custnum
FROM orders x
LEFT
JOIN orders y
ON y.custnum = x.custnum
AND y.chemno <> x.chemno
WHERE x.chemno = 9377
AND y.order_id IS NULL;
The rest of this task has been left as an exercise for the reader

Mysql complex select query from 4 tables

I research almost 200 example pages about mysql complex queries but stuck in it.
This is my stucture
Table name: zones
zoneId | zoneName
------------------
Table name: customers
customesId | zoneId | customerName
----------------------------------
Table name: products
productId | productName
-----------------------
Table name: sales
sid | zoneId | customerId | productId | amount
----------------------------------------------
Is it possible to get the following output only with the query?
zoneName | customerName | productName | amount(SUM)
---------------------------------------------------
ZoneX | customerA | productName_1 | 10
| | productName_2 | 0
| | productName_3 | 4
| | productName_4 | 0
ZoneX | customerB | productName_1 | 7
| | productName_2 | 0
| | productName_3 | 4
| | productName_4 | 3
.......
I want to get as "0" even customer or product has no sale
I tried:
SELECT zones.zoneName
, customers.customerName
, products.productName
, SUM(amount) AS amount
FROM customers
INNER JOIN zones
ON customers.zoneId = zones.zoneId
LEFT JOIN sales
ON customers.customerId = sales.customerId
LEFT JOIN products
ON sales.productId = products.productId
You need to cross join all the customers to the products so that each customer has every product listed regardless of sale.
SELECT z.zoneName
, c.customerName
, p.productName
, SUM(coalesce(s.amount,0)) AS amount
FROM customers c
INNER JOIN zones z
ON c.zoneId = z.zoneId
CROSS JOIN PRODUCTS P
LEFT JOIN sales S
ON c.customerId = s.customerId
and s.productID = p.productID
GROUP BY z.zoneName
, c.customerName
, p.productName
You can try this query
SELECT c.zoneId ,c.customesId ,c.customerName,IF(s.amount IS NULL, 0 , s.amount)
FROM customers AS c, products AS p
LEFT JOIN sales AS s ON s.productId = p.productId and s.customersid = c.customersid
Hope this helps.

Tip on joining three tables

I'm trying to join a few tables as I'll need values that are within all of them.
I've tried two ways so far:
First way:
SELECT
o.`order_id` as `Order ID`,
o.`STATUS` as `Order Status`,
o.`date_created` as `Date Created`,
op.`SKU`,
op.`NAME`,
o.`STATE`,
op.`QUANTITY`,
c.`customer_id`
FROM
`orderProducts` op
INNER JOIN
orders o on op.order_id = o.order_id
INNER JOIN
customers c on c.customer_id = o.customer_id
WHERE
o.order_id IN (616898, 616901)
Second way:
SELECT
o.`order_id` as `Order ID`,
o.`STATUS` as `Order Status`,
o.`date_created` as `Date Created`,
op.`SKU`,
op.`NAME`,
o.`STATE`,
op.`QUANTITY`,
c.`customer_id`
FROM
`orders` o,
`orderproducts` op,
`customers` c
WHERE
o.order_id IN (616898, 616901)
AND
c.customer_id= o.customer_id
AND
o.order_id = op.order_id
Tables data:
orders
+----------------------------+------------+------+-----+
| Field | Type | Null | Key |
+----------------------------+------------+------+-----+
| order_id | int(11) | NO | PRI |
| customer_id | int(11) | YES | |
orderproducts
+----------------------------+------------+------+-----+
| Field | Type | Null | Key |
+----------------------------+------------+------+-----+
| order_id | int(11) | NO | |
customers
+----------------------------+------------+------+-----+
| Field | Type | Null | Key |
+----------------------------+------------+------+-----+
| customer_id | int(11) | NO | PRI |
Sorry, but I don't really know how to represent the data I want out, I'll try my best to explain it.
I want the columns in my select statement, from the orders 616898 and 616901.
The order_id field is the same in both the order and orderproducts tables. The customer_id field is the same in both the order and customers tables. It's like I'm adding extra columns SKU, NAME, QUANTITY from orderproducts table using the order_id to extract the correct ones and the column email, using the customer_id from the orders and the customers table.
You need to join the orders and customer with customer_id and its always better to do joining using ids.
So the query would be
SELECT
o.`order_id` as `Order ID`,
o.`STATUS` as `Order Status`,
o.`date_created` as `Date Created`,
op.`SKU`,
op.`NAME`,
o.`STATE`,
op.`QUANTITY`,
c.`email`
FROM
`orders` o
INNER JOIN
orderProducts op on op.order_id = o.order_id
INNER JOIN
customers c on c.customer_id = o.customer_id
WHERE
o.order_id IN (616898, 616901)
Now what this will do
It will try joining all the tables if there is a matching data i.e. if the same order_id is on orders and in orderproducts and same customer_id is in orders and customers
Finally filter data only to 616898 or 616901
Note that if there is no matching data available for the given filter then you may not get the result. If you still want that data should be returned from orders table even if there is no match and joining table data as null you may need to change the inner join to left join

How to select the SUM of the multiplication of two different table fields specifying the value of other two fields?

Based on this table schema:
products
+----+------+-------+--------+--------------+-------+-------+------+-------+
| Id | Name | Price | Detail | Product_type | Image | Color | Size | Stock |
+----+------+-------+--------+--------------+-------+-------+------+-------+
order_details
+----+------------+--------+------+-------+----------+
| Id | Product_id | Amount | Size | Color | Order_id |
+----+------------+--------+------+-------+----------+
orders
+----+-----------+------------+----------+
| Id | Client_id | Date_start | Date_end |
+----+-----------+------------+----------+
How can I select the SUM() (if this function it's even necessary) of products.Price * order_details.Amount specifying the client and the order id?
I've tried with this query, among others:
SELECT SUM((SELECT pr.Price FROM products pr WHERE pr.Id = od.Product_id) * od.Amount) AS Total
FROM order_details od
WHERE (SELECT o.Client_id FROM orders o WHERE o.Id = $order) = $client
But it's returning a wrong result and I can't figure out how to do it. Also please note I want to use subqueries.
Thanks.
Dno't use a subselect, use a join:
SELECT orders.Id, SUM(products.Price * order_details.amount)
FROM orders
LEFT JOIN orders_details ON orders.Id = order_details.Order_id
LEFT JOIN products ON products.Id = order_details.Product_id
GROUP By orders.Clien_id, orders_details.Product_id