Count function returning wrong value when joined - mysql

I am trying to find a count of actions completed along with company details for companies who have more than 10 users.
The code I am using is:
SELECT
c.company_name,
count(a.action) as actions,
count(u.user_id) as users
FROM
companies c
LEFT JOIN
auditing a on c.id=a.company_id
LEFT JOIN
users u on c.id=u.company_id
GROUP BY
c.id
HAVING
count(u.user_id)>10
LIMIT
10
When I run this it displays an incorrect number of actions.
For example, for the first company in the table it returns:
Company 1,111026,111026
whereas it should return:
Company 1,5093,22
I need to get back the number of actions and the number of users for all companies - how can I do this?

try putting in DISTINCT so that way you aren't counting duplicates
SELECT
c.company_name,
count(DISTINCT a.action) as actions,
count(DISTINCT u.user_id) as users
FROM
companies c
LEFT JOIN
auditing a on c.id=a.company_id
LEFT JOIN
users u on c.id=u.company_id
GROUP BY
c.id
HAVING
count(u.user_id)>10
LIMIT
10

Related

Wrong use of inner join function / group function?

I have the following problem with my query:
I have two tables:
Customer
Subscriber
linked together by customer.id=subscriber.customer_id
in the subscriber table, I have records with id_customer=0 (these are email records, that do not have a full customer account)
Now i want to show how many customers I have per day, and how many subscribers with id_customer, and how many subscribers WITH id_customer=0 (emailonlies i call them)
Somehow, i cannot manage to get those emailonlies.
Perhaps it has something to do with not using the right join type.
When i use left join, i get the right amount of customers, but not the right amount of emailonlies. When I use inner join i get the wrong amount of customers. Am i using the group function correctly? i think it has something to do with that.
THIS IS MY QUERY:
` SELECT DATE(c.date_register),
COUNT(DISTINCT c.id) AS newcustomers,
COUNT(DISTINCT s.customer_id) AS newsubscribedcustomers,
COUNT(DISTINCT s.subscriber_id AND s.customer_id=0) AS emailonlies
FROM customer c
LEFT JOIN subscriber s ON s.customer_id=c.id
GROUP BY DATE(c.date_register)
ORDER BY DATE(c.date_register) DESC
LIMIT 10
;`
I'm not entirely sure, but I think in DISTINCT s.subscriber_id AND s.customer_id=0, it runs the AND before the DISTINCT, so the DISTINCT only ever sees true and false.
Why don't you just take
COUNT(DISTINCT s.subscriber_id) - (COUNT(DISTINCT s.customer_id) - 1)?
(The -1 is there because DISTINCT s.customer_id will count 0.)
Got it, only risk is that i get no email onlies if there are no customers on this day, becuase of the left join. But this one works:
SELECT customers.regdatum,customers.customersqty,subscribers.emailonlies
FROM (
(SELECT DATE(c.date_register) AS regdatum,COUNT(DISTINCT c.id) AS customersqty
FROM customer c
GROUP BY DATE(c.date_register)
) AS customers
LEFT JOIN
(SELECT DATE(s.added) AS voegdatum,COUNT(DISTINCT s.subscriber_id) AS emailonlies
FROM subscriber s
WHERE s.customer_id=0
GROUP BY DATE(s.added)
) AS subscribers
ON customers.regdatum=subscribers.voegdatum
)
ORDER BY customers.regdatum DESC
;

MySQL select count with join

I am trying to get a list of data from multiple tables in a view for analytics - most of the data comes from one table and then I need to get the counts from multiple other tables to show number of logins, number of users and so on.
I am using the below query (simplified to show only some rows and one join):
Select
companies.company_name, companies.last_login, companies.last_ip,
(SELECT COUNT(*) FROM auditing_master GROUP BY company_id) AS audit_count
From
companies
Left Join
auditing_master On auditing_master.company_id = companies.id
Group by
companies.id
When I run this I get an error:
#2014 - Commands out of sync; you can't run this command now
If I run it without the GROUP BY in the SELECT COUNT (*) then it doesn't give any error but it returns a count of all entries in the auditing_master table regardless of which company it refers to.
How can I get a single query to show me the required data from the companies table whilst also showing a total from auditing master (and others) grouped by the company ID?
Edit
Code when using multiple count/joins:
Select
c.company_name, c.last_login, c.last_ip,
COUNT(am.company_id) AS audit_count,
COUNT(u.company_id) AS users,
COUNT(e.company_id) AS employees
From
companies c
Left Join
auditing_master am On am.company_id = c.id
Left Join
users u On u.company_id = c.id
Left Join
employees e On e.company_id = c.id
Group by
c.id
This query locally in PHPMyAdmin on WAMP with only around 10 companies takes 7 seconds to complete and give "meanngless" results that don't correlate to anything.
Thanks
Inner queries in the SELECT clause must return a SINGLE VALUE RESULT.
Something similar to that, should bring what u need.
Select
companies.company_name, companies.last_login, companies.last_ip,
COUNT(*) AS audit_count
From
companies
Left Join
auditing_master On auditing_master.company_id = companies.id
Group by
companies.id
Did you try this? (No need a subquery because no where clause into it, and LEFT JOIN already add auditing_master rows grouped by company_id = companies.id)
Select
companies.company_name, companies.last_login, companies.last_ip,
COUNT(company_id) AS audit_count
From
companies
Left Join
auditing_master On auditing_master.company_id = companies.id
Group by
companies.id
EDIT
Maybe if you add IF statement to avoid COUNT when there is no auditing_master for a given company.
SELECT
companies.company_name, companies.last_login, companies.last_ip,
IFNULL(am.company_id,0,COUNT(am.company_id)) AS audit_count
FROM
companies
INNER JOIN
auditing_master am ON auditing_master.company_id = companies.id
GROUP BY
companies.id
Feel free to put the entire SQL... Because the problem can be somewhere else!

Running an SQL query in the loop of another SQL query?

So I have the following query which fetches Active Competitions within an organisation and also tries to fetch the user who is leading the competition.
Currently the query correctly fetches the active competitions, and the totalPoints for each user. It now grabs all users, I only want it to grab the top user, so I am assuming the solution lies in the GROUP BY query, some sort of LIMIT?
In this image, you can see the results I am getting. As you can see, I am getting every user for each competition, where I only need the top user for each competition.
http://i.imgur.com/5OXen4e.png
Any idea on how I could solve this?
SELECT c.competitionId, c.name, c.start_date, c.end_date, a.userid, u.name, u.profilePic ,
SUM(activity_weight) AS totalPoints
FROM activity_entries a INNER JOIN users1 u ON u.id = a.userid INNER JOIN competitions c ON c.competitionId = a.competitionId
WHERE c.organisationId = 1 AND c.start_date < now() AND c.end_date > now()
GROUP BY a.userid, c.competitionId ORDER BY c.id DESC
There is a better way. Just run one query with and join to the competitions table. The second query you posted shows that you know how to join tables.

MySQL Select customers without an active order with JOIN

So, I am trying to select customers that are completely inactive with MySQL join. I have the following statement that selects all the customers with an active service order.
SELECT DISTINCT u.* FROM users u INNER JOIN orders o ON o.assigned=u.id AND o.status!=0
This works just fine. But now I am trying to select customers who previously had an order but the order became deactivated (o.status would equate to the value 0). I have the following statement (which is close) but it is returning customers who still have an active order, but have another order which was deactivated.
SELECT DISTINCT u.* FROM users u INNER JOIN orders o ON o.assigned=u.id AND o.status!=1
So in layman term, basically a customer can have multiple service orders. Every service being independent from one another, I want to select the customers who are COMPLETELY deactivated. For example:
Susan has 2 service orders, 1 which is activated and the other deactivated. Right now, Susan is being populated in the list of users who are deactivated and that is incorrect. Only the customers whose orders are completely deactivated.
Thank you!
SELECT u.*
FROM users u
LEFT
JOIN orders o
ON o.assigned=u.id
AND o.status!=0
WHERE o.assigned IS NULL;
or something like that
In order to account for this scenario, you need to do a WHERE clause that would include the opposite SELECT statement.
For example:
select distinct u.* from users u inner join orders o
on o.assigned=u.id and o.status!=1
where u.id != (select distinct s.id from users s inner join orders r
on r.assigned = s.id and r.status!=0 where s.id == u.id)

Hybrid Left/Right Join based on condition?

I'm trying to write an SQL statement to retrieve a list of users from a database, along side their company name (if they have a company associated with them). However, there are a couple gotchas:
Not all users have companies, but I still need to show these people in the list.
Even if a user has a company, that company could be soft-deleted (the record is still in the database, but is flagged with is_deleted = 1), and I don't want to show users that are associated with "deleted" companies.
So essentially I want to SELECT from the User table and LEFT JOIN the company table, but I don't want to include the User record at all if the company they are assigned to is_deleted.
My first inclination is that I would have to use a UNION to merge two queries together, but I was hoping there would be a cleaner way to do it?
Using Mysql 5.1
SELECT U.name Username, C.name Company
FROM User U
LEFT OUTER JOIN Company C
ON U.companyid = C.id
WHERE C.id IS NULL OR C.is_deleted = 0
C.id IS NULL gets the users with no company, and C.is_deleted = 0 gets the users with companies that haven't been soft-deleted.
Try joining to a table that excludes the deleted companies:
SELECT U.Name, C.Name
FROM User U LEFT OUTER JOIN
(SELECT CompanyId, CompanyName
FROM Company
WHERE is_deleted = 0)
C ON U.CompanyId = C.CompanyId