Count() using Where clause and Left Join - mysql

I have a query similar to the following:
SELECT
users.id FROM users LEFT JOIN sales ON installations.customer = users.id
What I would like to say is something like "WHERE count(sales.id) > 4" - meaning that if the user has more than 4 sales assoc with them. I am not sure if I am going about this the wrong way or not though

select
users.id
from users
join sales on /* your join condition here */
group by users.id
having count(sales.id) > 4
This will group all of the sales by user, then return only those sales that have more than four records in the sales table.
I didn't duplicate your join condition from above because it didn't seem to make much sense, as it's referencing tables that aren't in your query anywhere.

I think you want something similar to this
select users.id, count(sales.id)
from users
LEFT JOIN sales ON installations.customer = users.id
group by users.id
having count(Sales.id) > 5

You need to use "group by" and "having" clause.
Try
SELECT users.id FROM users LEFT JOIN sales ON installations.customer = users.id GROUP BY users.id HAVING count(sale.id) > 4
See here for more GROUPBY on W2C

Related

MySQL - how to combine three tables to get the counts

There are three tables, I would like to get the count of a user's total tweets and the count of likes his total tweets received.
I tried to combine two queries to get what I want but failed. Have looked through several previous questions but still can't figure it out.
Users table
id
name
1
User1
Tweets table
id
UserId (foreign key)
content
1
User1
hello
Likes table
id
UserId (foreign key)
TweetId (foreign key)
1
User1
hello
First query:
SELECT Users.name, Users.id, COUNT(Tweets.UserId) AS UserTweetCount FROM Users
LEFT JOIN Tweets
ON Users.id = Tweets.UserId
GROUP BY Users.id
ORDER BY UserTweetCount DESC;
Second query:
SELECT Users.name, Users.id, COUNT(Likes.UserId) AS UserTweetBeLikedCount FROM Users
LEFT JOIN Likes
ON Users.id = Likes.UserId
GROUP BY Users.id;
I tried like below but would get wrong UserTweetBeLikedCount counts. The counts would be UserTweetCount's, not UserTweetBeLikedCount's. When I ran two queries separately, it worked well. But when I combined them together, it didn't work right.
Don't know how to display the right counts. Can someone give me hints to solve this, please?
SELECT Users.name, Users.id,
COUNT(Tweets.UserId) AS UserTweetCount, COUNT(Likes.UserId) AS UserTweetBeLikedCount
FROM Users
LEFT JOIN Tweets
ON Users.id = Tweets.UserId
LEFT JOIN Likes
ON Users.id = Likes.UserId
GROUP BY Users.id
ORDER BY UserTweetCount DESC;
I recommend using correlated subqueries for this:
SELECT u.*,
(SELECT COUNT(*)
FROM Tweets t
WHERE u.id = t.UserId
) AS UserTweetCount,
(SELECT COUNT(*)
FROM Likes l
WHERE u.id = l.UserId
) AS UserLikeCount
FROM Users u
ORDER BY UserTweetCount DESC;
As a note: For performance, you want indexes on Tweets(UserId) and Likes(UserId).

Combing a select statement with a count on a different table

I have two tables: users and lessons.
Currently I select all the users using:
SELECT * FROM users WHERE user_type = 1;
Then use PHP to loop through them and count their number of lessons using
SELECT COUNT(*) FROM lessons WHERE student_id=users.user_id;
I would like to combine this into a single query and I'm pretty sure this is possible with a JOIN but it is beyond my basic SQL knowledge.
Do this all in one query. If you want a count per user:
select u.user_id, count(l.student_id)
from users u left join
lessons l
on u.user_id = l.student_id
where u.user_type = 1
group by u.user_id
You can use a join, or a correlated subquery:
select
u.*,
(select count(*) from lessons l where l.student_id = u.user_id) no_lessons
from users u
The upside of the subquery solution is that it does not require aggregation in the outer query. With an index on lessons(student_id), this should be an efficient option.
You can write the following query for this:
SELECT * FROM users u LEFT JOIN lessons l ON u.user_id=l.student_id WHERE u.user_type=1 GROUP BY u.user_id
This will join both the tables (users and lessons) based on the id of both tables and the GROUP BY clause will group all the records of same id as you just want the number of lessons per user.

Data duplicate after join of four tables in Windows Form c# with MS Access

I am joining four tables i.e
users have user_history which workshop he is attending, so as room history where he is staying joining with room is to get name of the room which he is staying
Here is the query that is generate after joining above four tables in Ms Access query Design
SELECT
users.ID,
users.user_name,
users.father_name,
users.phone,
users.email,
users.cnic,
users.address,
users.user_type,
users.department,
users.designation,
users.emergency_no,
users.img,
room_history.ID,
room_history.room_id,
room_history.occupant_id,
room_history.start_date,
room_history.end_date,
rooms.room_name,
user_history.ID,
user_history.workshop
FROM (users
INNER JOIN (rooms
INNER JOIN room_history
ON rooms.room_id = room_history.room_id)
ON users.ID = room_history.occupant_id)
INNER JOIN user_history
ON users.ID = user_history.user_id;
Now the problem is that query works fine, but if user have multiple record in room_history and user_history table it returns four records i.e
In mysql this duplication is fixed by "GROUP BY" clause, that's not working here
I try to add "GROUP BY" to all fields it still cant work.
Note:
Üsers.Img data type is ole object so we cant add GROUP BY to it
Here is my query with GROUP BY clause, Still the result is same
SELECT DISTINCT
users.ID,
users.user_name,
users.father_name,
users.phone,
users.email,
users.cnic,
users.address,
users.user_type,
users.department,
users.designation,
users.emergency_no,
room_history.ID,
room_history.room_id,
room_history.occupant_id,
room_history.start_date,
room_history.end_date,
rooms.room_name,
user_history.ID,
user_history.workshop,
user_history.user_id
FROM (users
INNER JOIN (rooms INNER JOIN room_history ON rooms.room_id = room_history.room_id) ON users.ID = room_history.occupant_id)
INNER JOIN user_history ON users.ID = user_history.user_id
GROUP BY
users.ID,
users.user_name,
users.father_name,
users.phone,
users.email,
users.cnic,
users.address,
users.user_type,
users.department,
users.designation,
users.emergency_no,
room_history.ID,
room_history.room_id,
room_history.occupant_id,
room_history.start_date,
room_history.end_date,
rooms.room_name,
user_history.ID,
user_history.workshop,
user_history.user_id;
My comment captured part of what I wanted to say, but it's hard to articulate that in a tweet.
In essence, GROUP BY and/or SELECT DISTINCT, even if they work, are kind of masking the problem. The problem is that there are four records, and you want to pick one of them. If there is any distinction in the records, this won't work. More importantly, I think it's important that when you do this, and you want one record, you specify which record you want.
Let's assume, in your example if the room_history has multiple records for one occupant/room that you only want the most recent stay. In that case, assuming your DBMS supports the with clause and windowing functions, this would get you that:
with most_recent_history as (
select
ID, room_id, occupant_id, start_date, end_date,
max (end_date) over (partition by room_id, occupant_id) as last_date
from room_history
)
SELECT
users.ID,
users.user_name,
users.father_name,
users.phone,
users.email,
users.cnic,
users.address,
users.user_type,
users.department,
users.designation,
users.emergency_no,
users.img,
h.ID,
h.room_id,
h.occupant_id,
h.start_date,
h.end_date,
rooms.room_name,
user_history.ID,
user_history.workshop
FROM
users
INNER JOIN rooms
INNER JOIN most_recent_history h on
rooms.room_id = h.room_id and
users.ID = h.occupant_id and
h.end_date = h.last_date
INNER JOIN user_history on
users.ID = h.user_id;
If your DBMS does not support windowing functions and/or with, there are other ways to do this, but they're a lot more clumsy. If this is Oracle, SQL Server or PostgreSQL, this will work for sure.
Also, it doesn't seem possible in the real world, but in the event there can be a tie (a person is in two rooms that end on the exact same date), then you can add the tiebreaker to windowing function and use row_number instead.

Easy SQL Query - Aligning foreign keys

I'm taking longer than I expected with an easy Query in MySQL. I think it's gonna be a nested query but I don't see it easily.
I have 3 tables: Users, Comments, and Businesses. Comments have business_id, and user_id as foreign keys.
So I want the result of users.name and comments.review, having the number of the business.
So my First (and wrong) attempt was:
SELECT users.name, users.image, comments.review
FROM reviews JOIN users JOIN businesses
WHERE reviews.user_id=users.id AND reviews.business_id=4;
I want to set that PrimaryKey.user_id is equal to ForeignKey.users.id.
From all of the comments, I want to take these which are from the business_id=4.
It gives me failiure with both 'WHERE' clauses. So not sure if I could fix this with a nested query or maybe with a JOIN clause?
Any help will be appreciated!
Thank you all. [Edited Query]
Try this out and let me know in case of any queries.
select c.name,c.image,a.review
from
comments a
inner join
(select * from buisnesses where buisness_id = 4) b
on a.buisness_id = b.buisness_id
inner join
users c
on a.user_id = c.user_id;
or
select b.name,b.image,a.review
from
comments a
inner join
users b
on a.user_id = b.user_id
where a.buisness_id = 4;
Give this a try:
SELECT
users.name,
users.image,
comments.review
FROM reviews
JOIN users
ON reviews.user_id = users.id
JOIN businesses
ON reviews.business_id = business.business_id
WHERE reviews.business_id=4;
Since you're not using any of the columns from the business table, you could probably drop it from the query:
SELECT
users.name,
users.image,
comments.review
FROM reviews
JOIN users
ON reviews.user_id = users.id
WHERE reviews.business_id=4;

Order of join conditions important?

Consider this query
SELECT users.id,
users.name
FROM users
LEFT JOIN suppliers
ON users.id = suppliers.id
AND users.hall = suppliers.hall
WHERE USER.payment > 300
In this how will the change of order in the conditions of join matter ( i.e. id second and hall first)?
The order of the Join conditions has no effect on the result since they represent a boolean expression which is analysed in whole.