Query for multiple tables - mysql

I'm trying understand how I can pull information from multiple tables at once in one query if that is possible.
I have 3 tables and I'm wondering if there is a way I can query all the product names for customers that live in california?
Table:
products
Fields:
productOid
productName
companyOid
Table:
customerData
Fields:
customerOid
firstName
lastName
state
Table:
orders
Fields:
orderNumber
customerOid
productOid
Would this fall under something like an INNER JOIN?
Also, I'm learning mySQL.

You will need to use inner joins for this.
SELECT DISTINCT p.productName
FROM orders o
INNER JOIN customerData c ON o.customerOid = c.customerOid
INNER JOIN products p ON o.productOid = p.productOid
WHERE c.state = 'CA';
I am using DISTINCT here because it's possible a customer would order the same product more than once (or multiple customers would order the same products) and I'm assuming you don't want duplicates.
I'm also making the assumption that your state is represented as a two character column.
Read more about joins

You could use one more join, but I would write it this way:
SELECT DISTINCT p.productName
FROM
orders o INNER JOIN products p
ON o.productOid = p.productOid
WHERE
o.customerOid IN (SELECT customerOid
FROM customerData
WHERE state = 'California')
It might be a little slover than a join, but it's more readable.

This shows products that CA customers have ordered:
SELECT p.productName
FROM orders o
INNER JOIN products p ON o.productOid = p.productOid
INNER JOIN customerData c ON o.customerOid = c.customerOid
WHERE c.state = 'CA'

Related

mysql count rows from two tables in one query?

I have two MySQL-tables:
Persons (pid,name,companyID,companyName)
Orders (oid,companyID,details)
Now I want to count the number of order_id for each companyName as following:
Name Total
-------------------
CompanyName1 : 1200
CompanyName2 : 758
CompanyName3 : 11
I used this query but it's not working properly.
SELECT count(o.oid) as total,p.companyName
FROM orders as o, persons as p
WHERE o.companyID = p.companyID
GROUP BY p.companyName
Use join and group the result by p.companyID
SELECT p.companyName, count(o.oid) as total
FROM orders as o join persons as p
on o.companyID = p.companyID
GROUP BY p.companyID
If you are missing the companies without any orders you can use a left join.
SELECT p.companyName, count(*) as total
FROM persons p
LEFT JOIN orders o ON o.companyID = p.companyID
GROUP BY p.companyID, p.companyName
Please do not use the old, legacy join syntax any more - it is outdated since 1992.
Your data model looks messed up. That you have company ids and names in the person table but no corresponding companies table is highly suspicious.
In any case, presumably there can be multiple rows per company. You can condense the persons table and then join:
SELECT c.companyName, COUNT(*) as total
FROM orders o JOIN
(SELECT DISTINCT companyId, companyName
FROM persons p
) c
ON o.companyID = c.companyID
GROUP BY c.companyName;
However, you should fix the data model so you have a real bona fide companies table -- especially because you seem to care about that entity.

How can I use COUNT and GROUP BY in MYSQL while still displaying all individual rows?

I am just trying some practise exercises with MYSQL. I have a dataset where I would like to get the names of customers who ordered two or more different kinds of item and how many of each kind of item they bought.
The query below gives me a row for each name of the purchaser. However, I also want to display what types of items they bought and how many of them. Ideally I would like to have the same number of rows for each customer for how many different items they bought.
SELECT firstname, familyname, description, quantity
FROM customers c
JOIN orders o ON o.custID = c.custID
JOIN lineitems l on o.orderID = l.orderID
JOIN items i on l.itemID = i.itemID
GROUP BY firstname
HAVING count(description)
The query below does give me a row for each item, how many items that person bought, and the name of the purchaser. However, it does not filter for customers who only bought one specific item anymore.
SELECT firstname, familyname, description, quantity
FROM customers c
JOIN orders o ON o.custID = c.custID
JOIN lineitems l on o.orderID = l.orderID
JOIN items i on l.itemID = i.itemID
WHERE EXISTS(
SELECT *
FROM customers
GROUP BY firstname
HAVING count(description) >= 2)
Basically I would like to combine both approaches where there are multiple rows for specific item for each customer, while also filtering out customers who only bought one type of item.
If you are running MySQL 8.0, you can do a window count in a subquery and filter in the outer query, like:
SELECT *
FROM (
SELECT
c.firstname,
c.familyname,
i.description,
l.quantity,
COUNT(*) OVER(PARTITION BY c.custID) cnt
FROM customers c
JOIN orders o ON o.custID = c.custID
JOIN lineitems l on o.orderID = l.orderID
JOIN items i on l.itemID = i.itemID
) x
WHERE cnt > 1
Note: it is a good practice to prefix column names with the alias of the table they belong to; this makes the query more readable and avoid clashes when the same column name exists across tables. I made a few assumptions and updated the query accordingly.

Getting info through 3 tables

I'm following the SQL tutorial from w3schools.
I want to get the value of all orders delivered by a shipper. I don't have any idea about how I can get these details as the info are in different tables and the INNER JOIN didn't worked for me.
Database: http://www.w3schools.com/sql/trysql.asp?filename=trysql_select_groupby
By now, I managed to get the number of orders by each shipper.
SELECT Shippers.ShipperName,COUNT(Orders.OrderID) AS NumberOfOrders FROM Orders
LEFT JOIN Shippers
ON Orders.ShipperID=Shippers.ShipperID
GROUP BY ShipperName;
How could I get the value of those?
To bring the Price of a Product into your query you will need to join in tables OrderDetails to the Order table on the Orders.Id and then join in the Products table to the OrderDetail table on ProductID
SELECT Shippers.ShipperName,
COUNT(Orders.OrderID) AS NumberOfOrders,
Sum(Products.price * OrderDetails.Quantity) AS SumOfPrice
FROM Orders
LEFT JOIN Shippers ON Orders.ShipperID = Shippers.ShipperID
LEFT JOIN OrderDetails ON ORders.OrderID = OrderDetails.OrderID
LEFT JOIN Products ON OrderDetails.ProductID = Products.ProductID
GROUP BY ShipperName;
I just stuck with LEFT JOIN here as your example used, but an INNER JOIN would work just as well and be more efficient.
The FROM clause of the SQL statement is one of the first parts of the SQL to run against your database. It establishes which tables we are grabbing information from and the relationship between those tables (using the ON keyword). So here we bring in 4 tables, and use the ON keyword to show the relationship between all of them using their respective IDs. Then we can add their fields to the SELECT portion of the SQL statement and aggregate where needed.
If you want the "sum" of the product prices, that would be very similar to what you already have. Note how you currently use the COUNT() function to get the count, you can use the SUM() function to get the total of any numeric column.
Something like this:
SELECT
Shippers.ShipperName,
COUNT(Orders.OrderID) AS NumberOfOrders,
SUM(Products.Price) AS PriceOfOrders
FROM
Orders
INNER JOIN Shippers ON Orders.ShipperID = Shippers.ShipperID
INNER JOIN OrderDetails ON Orders.OrderID = OrderDetails.OrderID
INNER JOIN Products ON OrderDetails.ProductID = Products.ProductID
GROUP BY
ShipperName
Or perhaps the price also needs to be multiplied by the quantity in this calculation? Something like this:
SELECT
Shippers.ShipperName,
COUNT(Orders.OrderID) AS NumberOfOrders,
SUM(Products.Price * OrderDetails.Quantity) AS PriceOfOrders
FROM
Orders
INNER JOIN Shippers ON Orders.ShipperID = Shippers.ShipperID
INNER JOIN OrderDetails ON Orders.OrderID = OrderDetails.OrderID
INNER JOIN Products ON OrderDetails.ProductID = Products.ProductID
GROUP BY
ShipperName
It's up to your understanding of the table structure and the data, really. But the concept is the same, grouping by a value and applying a calculation to the grouped values (count or sum).

SQL Join involving 3 tables, how to?

SQL newbie here.
So we have 3 tables:
categories(cat_id,name);
products(prod_id,name);
relationships(prod_id,cat_id);
It is a one-to-many relationship.
So, given a category name say "Books". How do I find all the products that come under books?
As an example,
categories(1,Books);
categories(2,Phones);
products(302,Sherlock Holmes);
relationships(302,1);
You need to JOIN the three tables.
SELECT p.*
FROM relationships r
INNER JOIN products p
ON p.prod_id = r.prod_id
INNER JOIN categories c
ON c.cat_d = r.cat_id
WHERE c.name = 'Books'
You have to join tables on related columns and specify WHERE clause to select all records where category name = 'Books'
SELECT p.*
FROM categories c
JOIN relationships r ON c.cat_id = r.cat_id
JOIN products p ON r.prod_id = p.prod_id
WHERE c.name = 'Books' -- or specify parameter like #Books
In SQL you often join related tables and beginners tend to join, whatever the situation. I would not recommend this. In your case you want to select products. If you only want to show products data, select from products only. You want to select products that are in the category 'Books' (or for which exists an entry in category 'Books'). Hence use an IN or EXISTS clause in order to find them:
select * from products
where prod_id in
(
select prod_id
from relationships
where cat_id = (select cat_id from categories where name = 'Books')
);
Thus you get a well structured query that tells the reader easily how the tables are related and what data you are actually interested in. Later, with different tables and data to select, this may keep you from duplicate result rows that you must get rid of by using DISTINCT or from getting wrong aggregates (sums, counts, etc.), because of mistakenly considering records multifold.
try this:
select p.Prod_id,p.name
from products p inner join relationships r on
p.prod_id = r.prod_id
where r.cat_id = (select cat_id from categories where name = 'books')
or
select p.Prod_id,p.name
from products p inner join relationships r on
p.prod_id = r.prod_id inner join categories c on c.cat_id = r.cat_id
where c.name = 'books'

SQL Join Query Confusion - MySQL

I have three tables in MySQL.
customers which has columns {id, name, and email}
products which has columns {id and name}
purchased which contains {id, customer}
product where customer and product are indexes of customers.id and products.id respectively.
I am a little confused on how to get the customer's name and all products he has purchased. Here is what I have and it is basically returning all possible combinations of products and customers instead of the specific customers info:
SELECT
customers.email,
products.name
FROM
customers, products, purchased
INNER JOIN
customers cu
ON
cu.id = purchased.customer
INNER JOIN
products pr
ON
pr.id = purchased.product
WHERE
purchased.customer = 1
I expect this to return all products purchased by a customer with ID of 1 but it is not. Can someone help me here?
You are mixing the explicit and implicit join and hence creating the issue.
You may have the query as below. In addition you have used alias for the joining tables and need to use them in the select as well.
SELECT cu.email, pr.name FROM purchased
INNER JOIN customers cu
ON cu.id = purchased.customer
INNER JOIN products pr
ON pr.id = purchased.product
WHERE pr.customer = 1