I have these tables:
Customer = {id,firstname,last name,street,city}
Invoice = {id, customerid, total}
Item = {invoiceid, item, productid, quantity, cost}
Product = {id, name, price}
I would like to get the first name of the customer and the list of products what he bought.
I have created an sql code:
select customer.firstname, product.name from product
inner join item on item.productid = product.id
inner join invoice on invoice.id=item.invoiceid
inner join customer on customer.id=invoice.customerid
where customer.id=24
the customer.id is 24, because on this id I should get only 3 items' name.
Unfortunately, I am getting multiplication of these items.
What should I repair in my query?
I am getting multiplication of these items.
That is how relational databases work when you ask for a join. You get a Cartesian Product of the matching records.
However, MySQL has a facility that lets you put multiple values into a single field - it's called group_concat:
SELECT
customer.firstname
, GROUP_CONCAT(product.name SEPARATOR ', ')
FROM product
INNER JOIN item ON item.productid = product.id
INNER JOIN invoice ON invoice.id=item.invoiceid
INNER JOIN customer ON customer.id=invoice.customerid
WHERE customer.id=24
GROUP BY customer.id
Note the use of GROUP BY, which "merges" all rows for the same customer id into a single group, on which GROUP_CONCAT operates.
Related
I am trying to develop an enquiry management system for an institute.
I have 3 tables in mysql db.
leads_course_category table keeps course categories and has the columns: category_id, category_name, category_created_time, category_deleted.
leads_course_details table stores courses under categories and has the columns: course_id, course_category_id, course_name.
leads_enquiry_details table stores enquiry details and has the columns: enquiry_id, enquiry_name, leads_course_details_course_id, enquiry_deleted
I need to find the number of enquiries for each category.
I tried the following query:
SELECT category_name,COUNT(*) as COUNT
FROM leads_course_category
RIGHT JOIN leads_course_details
on category_id=leads_course_details.course_category_id
RIGHT JOIN `leads_enquiry_details`
on leads_course_details.course_id= leads_enquiry_details.leads_course_details_course_id
WHERE leads_enquiry_details.enquiry_deleted=1
GROUP BY leads_course_category.category_id
This query skips all the categories having null values, but I need to show that as count of zero.
Please help me to resolve this.
The condition enquiry_deleted = 1 must be moved to the ON clause:
select c.category_name, count(ed.enquiry_id) count
from leads_course_category c
left join leads_course_details cd on c.category_id = cd.course_category_id
left join leads_enquiry_details ed on cd.course_id = ed.leads_course_details_course_id and ed.enquiry_deleted = 1
group by c.category_id, c.category_name
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.
working with mySql I would like to list all purchases that customers made on a specific cathegory of products.
So, I had 3 tables: customers (idCustomer, Name) , cathegories (idCategory, CategoryName) and orders (idOrder, idCustomer, idCathegory, Qty, Price)
But I want a listing with ALL of the customers.
Not only the one who bought that specific idCategory
I thought something like:
select sum(Orders.Qty), Customers.Name
from Orders
right join Customers on Orders.idCustomer = Customer.idCustomer
where Orders.idCategory = 'Notebooks'
group by Orders.idCategory
but this statement only lists the records for customers who exists in Orders table.
And I want all of them ( the one who didnt buy, with qty =0 )
thanks in advance
Most people find left join easier to follow than right join. The logic for left join is to keep all rows in the first table, plus additional information from the remaining tables. So, if you want all customers, then that should be the first table.
You will then have a condition on the second table. Conditions on all but the first table should be in the on clause rather than a where. The reason is simple: when there is no match, then the value will be NULL and the where condition will fail.
So, try something like this:
select sum(o.Qty) as sumqty, c.Name
from Customers c left join
Orders o
on o.idCustomer = c.idCustomer and
o.idCategory = 'Notebooks'
group by c.Name;
Finally, the group by should have a relationship to the select clause.
Try this query
select sum(Orders.Qty), Customers.Name
from Customers
right join Orders on Customer.idCustomer = Orders.idCustomer and Orders.idCategory = 'Notebooks'
group by Customers.Name
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
3 tables in database:
Supplier(id, name, address)
Product(id, name, detail)
Product_Supplier(id, productId, supplierId, quantity)
Now I want to get all products (which are supplied by all suppliers) and their quantity if they are supplied by supplier 1 (supplierId = 1). How can I do that in a single sql query?
Update: I can do that if use multiple queries: first I get product information from Product table then query Product_Supplier table with productId and supplierId. Do all in one query is shorter, but is it more efficient?
Using a LEFT OUTER JOIN will allow you to list all products, but only get the quantity for the products supplied by supplier one. You just need to use the supplierId constraint in the join condition.
SELECT Product.*,
Product_Supplier.quantity
FROM Product
LEFT OUTER JOIN Product_Supplier ON Product.id = Product_Supplier.productId
AND Product_Supplier.supplierId = 1