mysql: list number of orders all customers made - mysql

I have 2 simple tables like customers and orders where a customer can have 0 to n orders. I would like to have a list like:
10 customers made 0 orders
4 customers made 1 order
5 customers made 2 orders
2 customers made 3 orders
... and so on. So far I have:
SELECT customers.id FROM customers
LEFT JOIN orders ON orders.customerId = customers.id
HAVING COUNT(orders.id) = 1;
which lists me all customers who made 1 order, but as I said I need a list with all possebilities.

SELECT COUNT(*), t.orderCount
FROM
(
SELECT u.id, COUNT(o.id) AS orderCount
FROM users u LEFT JOIN orders o
ON u.id = o.userId
GROUP BY u.id
) t
GROUP BY t.orderCount
The inner query will give each user and his order total:
user total
1 2
2 3
3 2
4 3
The outer query does a GROUP BY this total to count the number of customers who share the total:
# customers total
2 2
2 3

You can use aggregate function and group bu
SELECT ifnull(count(orders.id),0), users.id FROM users
LEFT JOIN orders ON orders.userId = users.id
group by users.id

Related

SQL query to join one to many relation with many to many relation

I have the following structure
COFFEE ORDER_ITEMS ORDERS USERS
------ ----------- ------ -----
id order_id id id
name coffee_id user_id email
There is a many to many relation between orders and coffees. And a one to many relation between users and orders. I would like to know what coffees a user has ordered.
I have a query to retrieve the orders per user:
SELECT users.id as USERID, orders.id as ORDERID
FROM users
INNER JOIN orders on users.id = orders.user_id
As an example this gives me:
userid orderid
1 1
1 2
2 3
4 4
I have a query to retrieve the coffees that belong to an order:
SELECT orders.id, coffees.name
FROM orders, coffees, order_coffees
WHERE coffees.id = order_coffees.coffee_id
AND orders.id = order_coffees.order_id
As an example, this gives me:
orderid coffeename
1 Coffee A
1 Coffee B
2 Coffee A
2 Coffee C
I would like to get the following:
userid orderid coffeename
1 1 Coffee A
1 1 Coffee B
1 2 Coffee A
2 3 Coffee C
4 4 NULL
You should join all 4 tables starting from the table users and use INNER joins if you want results only for the users who have ordered a coffee at least once, or LEFT joins if you want results for all users, even the ones who have never placed and order.
Use proper joins with ON clauses and aliases for the tables to make the code more readable:
SELECT u.id userid,
o.id orderid,
c.name coffeename
FROM users u
INNER JOIN orders o ON o.user_id = u.id
INNER JOIN order_items oi ON oi.order_id = o.id
INNER JOIN coffees c ON c.id = oi.coffee_id;
data sheet
1.main order(master_list)
3.Order Details(booking)
3.coffee Meals(shop)
4.user information(user)
SELECT * FROM `booking` as a
inner join `master_list` as b on a.`mas_id`=b.`mas_id`
inner join `shop` as c on a.`shop_id`=c.`shop_id`
inner join `user` as d on b.`user_id`=d.`user_id`
I don't know if it helps you try it

MySQL How to GROUP BY counted column?

I have two tables users, orders
each table has below column
users(table)
id
orders(table)
user_id
How can i get the number of users whose order count is 1,2,3,4 ....n?
Like this?
users count | order count
999 | 1
100 | 2
80 | 3
70 | 4
60 | 5
50 | 6
What I have been trying so far is
SELECT cnt.uid as u_cnt, cnt.ocnt as or_cnt
FROM (
SELECT u.id as uid, COUNT(o.id) as o_cnt
FROM users as u
INNER JOIN orders o on u.id = o.user_id
) as cnt;
GROUP BY or_cnt
BUT I get only 1 u_cnt and summed or_cnt
You need two levels of group by clauses here: First, you need to group by user and count the number of orders each user has. Then, you need to take that result, group by the number of orders and count how many users have such an order count.
The easiest way to achieve this is probably with a subquery, where both the inner and outer query have a group by clause:
SELECT cnt.ocnt as or_cnt, COUNT(*) as user_count
FROM (
SELECT u.id as uid, COUNT(o.id) as o_cnt
FROM users as u
INNER JOIN orders o on u.id = o.user_id
GROUP BY u.id -- This was missing in your original query
) as cnt
GROUP BY or_cnt
You can use two levels of aggregation. More importantly, you do not need a JOIN. All the information you need is in orders:
SELECT o_cnt, COUNT(*) as user_count
FROM (SELECT o.user_id, COUNT(*) as o_cnt
FROM orders o
GROUP BY o.user_id
) u
GROUP BY o_cnt
ORDER BY o_cnt;

MYSQL JOIN query to group user skills for conditional count

I am struggling to find the logic for a JOIN query with GROUP BY.
I have 3 tables.
1. tbl_users
2. tbl_event_orders
3.tbl_event_signature ( For saving signatures on completed events)
tbl_users
id name skill
---------------------------
1 user1 A
2 user2 B
3 user3 A
4 user4 A
tbl_orders
id user_id item_id price
------------------------------------
1 1 1 100
2 2 1 100
3 3 1 100
4 4 1 100
tbl_signature
id item_id user_id signature
----------------------------------------------
1 1 1 xxxxxxxx...
1 1 3 NULL
1 1 4 xxxxxxxx...
I need the event details from item id.
For example for item with id 1, I need the following result.
skill total_count attended_users_count amount
A 3 2 300
B 1 0 100
skill - skill from user table.
total_count - total count of orders from that partical skill.
attended_users_count - total count of orders from that partical skill + this should have an entry and a NOT NULL value in tbl_signature table.
amount - sum of price(total_count)
I have the following query for getting users with skills and total count.
SELECT
U.skill as skill,
count(U.skill) as total_count,
sum( O.price ) as amount
FROM tbl_users U
INNER JOIN tbl_orders O
ON U.id = O.user_id
WHERE O.item_id = 1
GROUP BY U.skill
but when dealing with attended users count, I am getting unexpected results.
I have tried with the following query,
SELECT
U.skill as skill,
count(U.skill) as total_count,
count( S.signature ) as attended_users_count,
sum( O.price ) as amount
FROM tbl_users U
INNER JOIN tbl_orders O
ON U.id = O.user_id
LEFT JOIN tbl_signature S
ON O.item_id = S.item_id
WHERE O.item_id = 1
GROUP BY U.skill
Is there any way to get this in a single query?
This query should give you the results you want. It JOINs tbl_orders to tbl_users, and then LEFT JOINs to tbl_signature. Rows of tbl_signature which don't match, or which don't have a signature, will not get included in the count for that order:
SELECT u.skill,
COUNT(o.id) AS total_count,
COUNT(s.signature) AS attended_users_count,
SUM(o.price) AS amount
FROM tbl_orders o
JOIN tbl_users u ON u.id = o.user_id
LEFT JOIN tbl_signature s ON s.item_id = o.item_id AND s.user_id = u.id
WHERE o.item_id = 1
GROUP BY u.skill
Output:
skill total_count attended_users_count amount
A 3 2 300
B 1 0 100
Demo on dbfiddle

Get the number of users that belong to a group and the number of orders that belong to the group through its users

I have a user_groups table, a users table and an orders table.
The relationship between them is this: users.group_id, orders.user_id.
I'm trying to get the amount of users that belong to each group, and the amount of orders that belong to each group through its users.
My code:
select user_groups.*, count(users.id) as user_count, count(orders.id) as order_count
from user_groups
left join users on user_groups.id=users.group_id
left join orders on users.id=orders.user_id
group by user_groups.id
Expected output:
id | user_count | order_count
1 | 5 | 67
2 | 1 | 1
Actual output:
The amount of orders should be 5, not 71:
Use count(distinct):
select ug.*, count(distinct u.id) as user_count, count(distinct o.id) as order_count
from user_groups ug left join
users u
on ug.id = u.group_id left join
orders o
on u.id = o.user_id
group by ug.id;
count(id) counts the number of non-NULL values. You apparently want to count the number of different values, which is what distinct does.

Show recurrent clients in this query

I have a query that shows me the amount of client per amount of orders placed.
select quantidade_pedidos, count(*)
from (select count(*) as quantidade_pedidos, c.id
from pedidos p inner join
clientes c
on p.cliente_id = c.id
where p.aprovado = 1
group by c.id
) x
group by quantidade_pedidos;
I want to make clients that have placed 2 orders be listed in 1, clients that have placed 3 orders be listed in 2 etc as well.
Now it only groups by number of orders:
1 order - 700 clients
2 orders - 300 clients
3 orders - 100 clients
Those 300 clients must appear in the 1 order to because they placed 1 order and 2 orders and those 100 clients must appear in the 2 orders group because they placed two orders.
How can I correct this query?
Sorry if it got a little bit confusing.
Thanks
If I understand then what you want is to also group by the number of orders by adding a second group by.
select quantidade_pedidos, count(*) as order_count
from (select count(*) as quantidade_pedidos, c.id
from pedidos p inner join
clientes c
on p.cliente_id = c.id
where p.aprovado = 1
group by c.id
) x
group by quantidade_pedidos, order_count;