Get quantity per product in each order using MySQL - mysql

I have 3 tables, order, products, and orders_products and I'm trying to find out how many of each product was bought in each order. Is it possible to get all information in a single query?
My current query doesn't seem to work, whereas the product_id comes out as all the same.
SELECT orders.order_id, orders.username, COUNT( DISTINCT op.product_id ) product_id, SUM( op.quantity ) quantity
FROM `orders`
JOIN orders_products op ON op.order_id = orders.order_id
GROUP BY product_id, orders.order_id ORDER BY order_id, product_id
Which results in:
_______________________________________________
| order_id | username | product_id | quantity |
-----------------------------------------------
| 1 | bill | 1 | 3 |
-----------------------------------------------
| 1 | bill | 1 | 2 |
-----------------------------------------------
| 1 | bill | 1 | 5 |
-----------------------------------------------
| 2 | sally | 1 | 2 |
-----------------------------------------------
| 3 | jeff | 1 | 6 |
-----------------------------------------------
| 3 | jeff | 1 | 7 |
-----------------------------------------------
You can see the problem above in the product_id column which is always set to 1.
I'm trying to get something like this:
_______________________________________________
| order_id | username | product_id | quantity |
-----------------------------------------------
| 1 | bill | 1 | 5 |
-----------------------------------------------
| 1 | bill | 2 | 3 |
-----------------------------------------------
| 1 | bill | 3 | 2 |
-----------------------------------------------
| 2 | sally | 1 | 2 |
-----------------------------------------------
| 3 | jeff | 1 | 6 |
-----------------------------------------------
| 3 | jeff | 2 | 7 |
-----------------------------------------------
My tables:
-- Orders
_______________________
| order_id | username |
-----------------------
| 1 | bill |
-----------------------
| 2 | sally |
-----------------------
| 3 | jeff |
-----------------------
-- Products
___________________
| id | product |
-------------------
| 1 | Table |
-------------------
| 2 | Chair |
-------------------
| 3 | Mouse |
-------------------
-- Order Products
___________________________________________
| id | order_id | product_id | quantity |
-------------------------------------------
| 1 | 1 | 1 | 5 |
-------------------------------------------
| 2 | 1 | 2 | 3 |
-------------------------------------------
| 3 | 1 | 3 | 2 |
-------------------------------------------
| 4 | 2 | 1 | 2 |
-------------------------------------------
| 5 | 3 | 1 | 6 |
-------------------------------------------
| 6 | 3 | 2 | 7 |
-------------------------------------------

I think the query you want is:
SELECT o.order_id, o.username, op.product_id, SUM( op.quantity ) as quantity
FROM `orders` o JOIN
orders_products op
ON op.order_id = o.order_id
GROUP BY op.product_id, o.order_id
ORDER BY o.order_id, op.product_id;
In general, you do want all the columns in the GROUP BY in the SELECT. But (in general) they shouldn't be arguments to aggregation functions such as COUNT().

You can see the problem above in the product_id column which is always
set to 1
I think you are bit confused here, that's the data present in Order Products table for product_id column but in your query what you are trying to get is count of data COUNT( DISTINCT op.product_id ) product_id and since the count is 1, the result is showing the same.

Related

SELECT Query with COUNT and INNER JOIN

I am facing some difficulties since I'm not very experienced in SQL. So i have the tables:
----------------- -------------------
| membership_info | | client_info |
----------------- -------------------
| ID (PK) | | client_id (FK) |
| Name | | membership_id (FK)|
| Price | | value_paid |
----------------- -------------------
The membership_info and client_info has the values like:
-------------------------- ----------------------------------------
| ID | Name | Price | | client_id | membership_id | value_paid |
-------------------------- ----------------------------------------
| 1 | Daily | 30 | | 24 | 2 | 80 |
| 2 | Weekly | 80 | | 25 | 2 | 80 |
| 3 | Monthly | 100 | | 26 | 3 | 100 |
-------------------------- ----------------------------------------
Now the problem that I'm facing is that i cannot figure out how to query a result looking like this:
-------------------------------------
| Membership Name | Membership Count |
-------------------------------------
| Weekly | 2 |
| Monthly | 1 |
-------------------------------------
Please help!
select name, count(*)
from client_info c
inner join membership_info m on c.membership_id = m.id
group by name

mysql query for multiple foreign keys

mysql tables are as follows
+------------+----------------+----------------+
| booking_id | boarding_point | dropping_point |
+------------+----------------+----------------+
| 1 | 2 | 4 |
| 2 | 1 | 2 |
+------------+----------------+----------------+
+-------------+---------------+
| location_id | location_name |
+-------------+---------------+
| 1 | chennai |
| 2 | coimbatore |
| 3 | tiruppur |
| 4 | erode |
| 5 | salem |
+-------------+---------------+
boarding_point and dropping_point are foreign keys for location_id.
Now I want the select query to display like
+------------+----------------+----------------+
| booking_id | boarding_point | dropping_point |
+------------+----------------+----------------+
| 1 | coimbatore | erode |
| 2 | chennai | coimbatore |
+------------+----------------+----------------+
can anyone please suggest me the query to display like above.
Join the booking table twice to the location table:
SELECT
b.booking_id,
t1.location_name,
t2.location_name
FROM booking b
INNER JOIN location t1
ON b.boarding_point = t1.location_id
INNER JOIN location t2
ON b.dropping_point = t2.location_id;
Demo

Skip rows in the primary table if value found in secondary table MYSQL

I have this table (payments)
| id | amount | payment | frequency |
|----|--------|------------|-----------|
| 1 | 100 | 2017-05-15 | 12 |
| 2 | 200 | 2017-05-15 | 12 |
| 3 | 300 | 2017-05-17 | 4 |
And this one (payments_log):
| id | payment_id | payment |
|----|------------|------------|
| 1 | 1 | 2017-04-15 |
| 2 | 1 | 2017-05-15 |
| 3 | 2 | 2017-04-15 |
Here is my query:
SELECT p.id, p.amount, p.date AS payment_date, pl.date
FROM payments AS p
LEFT JOIN payments_log AS pl ON pl.payment_id = p.id
WHERE p.frequency = 12 AND
DATE_FORMAT(p.date,'%m-%d') IN ('06-15','07-15','08-15','09-15','10-15','11-15','12-15','01-15','02-15','03-15','04-15','05-15')
I only wants to returns records with the matched payment date but if there any record in the payments_log table with the current date then skip any record in the primary table:
| id | amount | payment | frequency |
|----|--------|------------|-----------|
| 2 | 200 | 2017-05-15 | 12 |
The ID 2 is valid because match with the '04-15' date but the record ID 1 is not valid because there is a payment_log with the current date.
Thanks.

MYSQL: Separate products into columns

This is in relation to my previous post MYSQL: Get quantity per product in each order.
Using the query below, it generates a table of:
SELECT o.order_id, o.username, op.product_id, SUM( op.quantity ) as quantity
FROM `orders` o JOIN
orders_products op
ON op.order_id = o.order_id
GROUP BY op.product_id, o.order_id
ORDER BY o.order_id, op.product_id;
_______________________________________________
| order_id | username | product_id | quantity |
-----------------------------------------------
| 1 | bill | 1 | 5 |
-----------------------------------------------
| 1 | bill | 2 | 3 |
-----------------------------------------------
| 1 | bill | 3 | 2 |
-----------------------------------------------
| 2 | sally | 1 | 2 |
-----------------------------------------------
| 3 | jeff | 1 | 6 |
-----------------------------------------------
| 3 | jeff | 2 | 7 |
-----------------------------------------------
As seen above, each new product_id is assigned its own row. Is it possible to have additional columns for each product_id instead of rows generating an output same as the one below?
_______________________________________________________________________
| order_id | username | product_qty_1 | product_qty_2 | product_qty_3 |
-----------------------------------------------------------------------
| 1 | bill | 5 | 3 | 2 |
-----------------------------------------------------------------------
| 2 | sally | 2 | 0 | 0 |
-----------------------------------------------------------------------
| 3 | jeff | 6 | 7 | 0 |
-----------------------------------------------------------------------
My tables:
-- Orders
_______________________
| order_id | username |
-----------------------
| 1 | bill |
-----------------------
| 2 | sally |
-----------------------
| 3 | jeff |
-----------------------
-- Products
___________________
| id | product |
-------------------
| 1 | Table |
-------------------
| 2 | Chair |
-------------------
| 3 | Mouse |
-------------------
-- Order Products
___________________________________________
| id | order_id | product_id | quantity |
-------------------------------------------
| 1 | 1 | 1 | 5 |
-------------------------------------------
| 2 | 1 | 2 | 3 |
-------------------------------------------
| 3 | 1 | 3 | 2 |
-------------------------------------------
| 4 | 2 | 1 | 2 |
-------------------------------------------
| 5 | 3 | 1 | 6 |
-------------------------------------------
| 6 | 3 | 2 | 7 |
-------------------------------------------
If you know the products in advance, you can use conditional aggregation:
SELECT o.order_id, o.username,
SUM(CASE WHEN op.product_id = 1 THEN op.quantity ELSE 0 END) as quantity1,
SUM(CASE WHEN op.product_id = 2 THEN op.quantity ELSE 0 END) as quantity2,
SUM(CASE WHEN op.product_id = 3 THEN op.quantity ELSE 0 END) as quantity3
FROM `orders` o JOIN
orders_products op
ON op.order_id = o.order_id
GROUP BY o.order_id
ORDER BY o.order_id;
If you don't know the product ids, then you would have to use dynamic SQL, or perhaps use GROUP_CONCAT() to create a string with the information you want.

Don't know how to merge two MySQL tables

I'm new in SQL queries. I have a problem with the query.
I have table books:
+----+-------+--------+-----------+
| id | title | author | publisher |
+----+-------+--------+-----------+
| 1 | Book1 | 1 | 1 |
| 2 | Book2 | 1 | 2 |
| 3 | Book3 | 2 | 1 |
| 4 | Book4 | 2 | 2 |
| 5 | Book5 | 2 | 3 |
+----+-------+--------+-----------+
And I'm have another table, which contains copies of books with given book_id.
+----+---------+
| id | book_id |
+----+---------+
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 2 |
| 5 | 2 |
| 6 | 3 |
| 7 | 4 |
| 8 | 4 |
| 9 | 5 |
+----+---------+
All I need is to merge these two tables into one to have table sorted by amount of book copies.
I found solution to get table sorted by amount of book copies:
select book_copies.book_id, count(*) total_count
from book_copies
group by book_id
having count(*) > 0
order by count(*) desc;
+---------+-------------+
| book_id | total_count |
+---------+-------------+
| 1 | 3 |
| 2 | 2 |
| 4 | 2 |
| 3 | 1 |
| 5 | 1 |
+---------+-------------+
Now I don't know how to merge them.
I've tried like this:
select books.title from books
left join
(select book_copies.book_id, count(*) total_count
from book_copies
group by book_id
having count(*) > 0
order by count(*) desc)
as total_table on books.id = total_table.book_id;
But all I get was this:
+-------+
| title |
+-------+
| Book1 |
| Book2 |
| Book3 |
| Book4 |
| Book5 |
+-------+
Could you help me please?
EDIT: by merging I meant smth like this:
+-------+--------+-----------+-----+
| title | author | publisher | tot |
+-------+--------+-----------+-----+
| Book1 | 1 | 1 | 3 |
| Book2 | 1 | 2 | 2 |
| Book4 | 2 | 2 | 2 |
| Book3 | 2 | 1 | 1 |
+-------+--------+-----------+-----+
Many thanks to #Marco for the answer!
Dmitriy
I think you could try:
SELECT b.title, b.author, b.publisher, COUNT(bc.book_id) AS tot
FROM books b LEFT JOIN book_copies bc
ON b.id = bc.book_id
GROUP BY b.id
EDITED:
If you want sort, you can try
SELECT * FROM
(SELECT b.title, b.author, b.publisher, COUNT(bc.book_id) AS tot
FROM books b LEFT JOIN book_copies bc
ON b.id = bc.book_id
GROUP BY b.id) g
ORDER BY g.tot DESC