MySQL count function with a join? - mysql

I've two tables.
User(id,name)
Finance(id,item_id,amount,user_id)
My use case is
users are the employees (sales guys) of the organization.
When they sell an item finance table get updated with a new record of that sold item's serial id.
I want to get the user names along with the total value of the sales they made.
User
id | name
1 | Dinesh
2 | Pathum
3 | Naveed
Finance
id | item_id | amount | user_id
1 | 1 | 2000 | 1
2 | 2 | 2000 | 1
3 | 3 | 1000 | 3
4 | 4 | 500 | 3
Expected output
Dinesh 4000
Pathum 0
Naveed 1500
How do I achieve this using MySQL?

The query is like the following:
SELECT u.name as 'Agent Name',
if(sum(f.amount) IS NULL, 0,sum(f.amount)) as Total,
f.createdAt
FROM users u LEFT JOIN finance f
ON u.id = f.user_id
GROUP BY u.id, u.name, f.createdAt
ORDER BY f.createdAt DESC
Here is a working SQL Fiddle.

Join em, group em, sum em.
SELECT usr.name AS UserName, COALESCE(SUM(fin.amount),0) AS TotalAmount
FROM `User` usr
LEFT JOIN `Finance` fin ON fin.user_id = usr.id
GROUP BY usr.id, usr.name
ORDER BY usr.id;
Test on db<>fiddle here

Another way:
SELECT Name,SUM(IFNULL(amount,0)) AS "Total" FROM (SELECT Name,amount FROM user LEFT JOIN finance ON user.id=finance.user_id) a GROUP BY Name;

Related

MYSQL GROUP BY LEFT JOIN and COUNT

I am having a problem grouping and counting items in a MYSQL database with JOIN clause
My two tables are as follows
users table
id | surname | othernames
1 | Doe | John
2 | Doe | Jane
3 | Doe | Mary
subscriptions table
id | user_id | parent_subscription_id
1 | 1 | Null
2 | 2 | 1
3 | 3 | 1
4 | 4 | 2
5 | 5 | 3
6 | 6 | 3
I need to be able to produce a list as follows
Name | Referrals
John Doe | 2
Jane Doe | 1
Mary Doe | 2
In other words,it Is the user in users table with the users.id which matches subscriptions.user_id that has the subscription with subscriptions.id which is a parent subscription to another subscription. That means, if your subscription is referenced by another subscription as its own parent_subscription_id, then that new subscription becomes your referral.
I have tried the following query and it is not giving me the expected results
SELECT users.surname, users.othernames,count('s.parent_subscription_id') as referrals
FROM users
LEFT JOIN subscriptions s ON s.user_id=users.id
group BY parent_subscription_id
I have checked some other questions on SO but I have not been able to find any that solves this type of issue
Thank you
I think that the logic you want is:
select u.surname, u.othernames, count(s.parent_subscription_id) referrals
from subscriptions s
left join subscriptions p on p.id = s.parent_subscription_id
inner join users u on u.id = coalesce(p.user_id, s.user_id)
group by u.id, u.surname, u.othernames
Demo on DB Fiddle:
surname | othernames | referrals
:------ | :--------- | --------:
Doe | John | 2
Doe | Jane | 1
Doe | Mary | 2
You ca use join between users table and select calculated count as:
SELECT
-- Get all users
users.surname,
users.othernames,
IFNULL(reff.cnt, 0) as referrals -- Preset 0 for users have not referrals in joined table
FROM users
-- Join calculation result
LEFT JOIN (
-- Calculate count by user
SELECT parent_subscription_id, COUNT(*) AS cnt
FROM subscriptions
GROUP BY subscriptions.parent_subscription_id
) reff on reff.parent_subscription_id = users.id;
Change group by fields with users.surname, users.othernames
SELECT users.surname, users.othernames,count(s.parent_subscription_id) as referrals
FROM users
LEFT JOIN subscriptions s ON s.user_id=users.id
group BY users.surname, users.othernames
you need to group by id of users table because you need get count for each user and here is your main table is users. try like this.
SELECT users.surname, users.othernames, count('s.parent_subscription_id') as referrals
FROM users
LEFT JOIN subscriptions s ON s.user_id = users.id
group BY users.id
This query eventually gave me the result I have been looking for
SELECT u.surname,u.othernames,s1.id,s1.parent_subscription_id,
s1.refcode, IFNULL(count(s2.parent_subscription_id),0) as referrals
FROM `subscriptions` s1 left join subscriptions s2
on s1.id=s2.parent_subscription_id
LEFT JOIN users u ON u.id=s1.user_id
GROUP by s1.id
Thank you all for your guidance and support on this. I deeply appreciate it

SQL left join: how to return the newest from tableB and grouped by another field

I've been trying for two days, without luck.
I have the following simplified tables in my database:
customers:
| id | name |
| 1 | andrea |
| 2 | marco |
| 3 | giovanni |
access:
| id | name_id | date |
| 1 | 1 | 5000 |
| 2 | 1 | 4000 |
| 3 | 2 | 1500 |
| 4 | 2 | 3000 |
| 5 | 2 | 1000 |
| 6 | 3 | 6000 |
| 7 | 3 | 2000 |
I want to return all the names with their last access date.
At first I tried simply with
SELECT * FROM customers LEFT JOIN access ON customers.id =
access.name_id
But I got 7 rows instead of 3 as expected. So I understood I need to use GROUP BY statemet as the following:
SELECT * FROM customers LEFT JOIN access ON customers.id =
access.name_id GROUP BY customers.id
As far I know, GROUP BY combines using a random row. In fact I got unordered access dates with several tests.
Instead I need to group every customer id with its corresponding latest access! How this can be done?
You have to get the latest date from the access table with a group by on the the name_id, then join this result with the customer table. Here is the query:
select c.id, c.name, a.last_access_date from customers c left join
(select id, name_id, max(access_date) last_access_date from access group by name_id) a
on c.id=a.name_id;
Here is a DEMO on sqlfiddle.
I think this is what you'd like to achieve:
SELECT c.id, c.name, max(a.date) last_access
FROM customers c
LEFT JOIN access a ON c.id = a.name_id
GROUP BY c.id, c.name
The LEFT join will return all entries in table customers regardless if the join criteria (c.id = a.name_id) is satisfied. This means that you might get some NULL entries.
Example:
Simply add a new row in the customers table (id: 4, name: manuela). The output will have 4 rows and the newest row will be (id: 4, last_access: null)
I would do this using a correlated subquery in the ON clause:
SELECT a.*, c.*
FROM customers c LEFT JOIN
access a
ON c.id = a.name_id AND
a.DATE = (SELECT MAX(a2.date) FROM access a2 WHERE a2.name_id = a.name_id);
If this statement is true:
I need to group every customer id with its corresponding latest access! How this can be done?
Then you can simply do:
select a.name_id, max(a2.date)
from access a
group by a.name_id;
You do not need the customers table because:
All customers are in access, so the left join is not necessary.
You need no columns from customers.

Return Number Of Times An ID Is Repeated

so I have two tables:
orders
order_id | user_id
1 | 1
2 | 1
3 | 1
4 | 2
5 | 2
users
user_id | name
1 | John
2 | Mike
I want to return the id, name of the client and how many orders he has placed. Something like this:
user_id | name | num_orders
1 | John | 3
2 | Mike | 2
I tried to do the following query but it only returns the first user's name and the total amount of orders. This is the query I have:
SELECT
users.user_id,
users.name,
COUNT(orders.order_id) AS num_orders
FROM users
LEFT JOIN orders
ON users.user_id = orders.user_id
ORDER BY users.user_id DESC
Any help is greatly appreciated! :)
You are missing a GROUP BY statement. If you add in at the end
GROUP BY users.user_id
it should rectify your issues.
For more help on SQL statements try http://www.dofactory.com/sql/tutorial
What you are looking for is a GROUP BY clause. It is used with aggregate functions (COUNT, MAX, MIN, SUM, AVG) to group the results by one or more columns. Here is how it works.
SELECT
users.name,
users.user_id,
count(users.user_id) as total
FROM users
LEFT JOIN orders ON users.user_id = orders.user_id
GROUP BY users.user_id
ORDER BY users.user_id DESC
And the results:
username |user_id | total
John | 3 | 3
Mary | 2 | 5
Carl | 1 | 1
...

Get total count of records with a mysql join and 2 tables

I have 2 tables that I am trying to join but I am not sure how to make it the most time efficient.
Tasks Table:
nid | created_by | claimed_by | urgent
1 | 11 | 22 | 1
2 | 22 | 33 | 1
3 | 33 | 11 | 1
1 | 11 | 43 | 0
1 | 11 | 44 | 1
Employee Table:
userid | name
11 | EmployeeA
22 | EmployeeB
33 | EmployeeC
Result I am trying to get:
userid | created_count | claimed_count | urgent_count
11 | 3 | 1 | 3
22 | 1 | 1 | 2
33 | 1 | 1 | 2
created_account column will show total # of tasks created by that user.
claimed_count column will show total # of tasks claimed by that user.
urgent_count column will show total # of urgent tasks (created or claimed) by that user.
Thanks in advance!
I would start by breaking this up into pieces and then putting them back together. You can get the created_count and claimed_count using simple aggregation like this:
SELECT created_by, COUNT(*) AS created_count
FROM myTable
GROUP BY created_by;
SELECT claimed_by, COUNT(*) AS claimed_count
FROM myTable
GROUP BY claimed_by;
To get the urgent count for each employee, I would join the two tables on the condition that the employee is either the created_by or claimed_by column, and group by employee. Instead of counting, however, I would use SUM(). I am doing this because it appears each row will be either 0 or 1, so SUM() will effectively count all non-zero rows:
SELECT e.userid, SUM(t.urgent)
FROM employee e
JOIN task t ON e.userid IN (t.created_by, t.claimed_by)
GROUP BY e.userid;
Now that you have all the bits of data you need, you can use an outer join to join all of those subqueries to the employees table to get their counts. You can use the COALESCE() function to replace any null counts with 0:
SELECT e.userid, COALESCE(u.urgent_count, 0) AS urgent_count, COALESCE(crt.created_count, 0) AS created_count, COALESCE(clm.claimed_count, 0) AS claimed_count
FROM employee e
LEFT JOIN(
SELECT e.userid, SUM(t.urgent) AS urgent_count
FROM employee e
JOIN task t ON e.userid IN (t.created_by, t.claimed_by)
GROUP BY e.userid) u ON u.userid = e.userid
LEFT JOIN(
SELECT claimed_by, COUNT(*) AS claimed_count
FROM task
GROUP BY claimed_by) clm ON clm.claimed_by = e.userid
LEFT JOIN(
SELECT created_by, COUNT(*) AS created_count
FROM task
GROUP BY created_by) crt ON crt.created_by = e.userid;
Here is an SQL Fiddle example.

SQL Count Rows From Multiple tables

Lets say i have 2 tables
Companies
company_id
name
Users
id
company_id
name
each company has multiple users assign to it... which is referenced in the company_id field from each record in the users table
HOW can i get a record showing the (company_id), (company_name) and (number or users)
for eg:
id# 1234 | name# Microsoft | n of users# 2000
I dont know how to make this query, i know i have to use the function COUNT() but i dont know how
If you want to get all companies even if they don't have any users yet use OUTER JOIN
SELECT c.company_id, c.name company_name, COUNT(u.id) no_of_users
FROM companies c LEFT JOIN users u
ON c.company_id = u.company_id
GROUP BY c.company_id, c.name
Sample output:
| COMPANY_ID | COMPANY_NAME | NO_OF_USERS |
|------------|--------------|-------------|
| 1 | Company1 | 3 |
| 2 | Company2 | 2 |
| 3 | Company3 | 0 |
Here is SQLFiddle demo
this will be the query
select Companies.company_id,Companies.name,count(Users .id) from Companies,Users where Companies=company_id and Users =company_id group by company_id
Try :
SELECT companies.company_id,companies.company_name,COUNT(users.id)
FROM companies, users
WHERE companies.id = users.company_id
group by companies.id