I have a table with three columns and one stores the users ip address. I want to query, but want to restrict it so that users with their ip in the ip_address column are only counted once. Here is my current query
SELECT COUNT(*) FROM articles where article_id = '1'
You want to count unique ip addresses? Use count(distinct)
SELECT COUNT(DISTINCT IP_address) FROM articles where article_id = '1'
Just to make it clear, here is what a solution with GROUP BY might look like:
SELECT COUNT(*) FROM (SELECT IP_address FROM articles GROUP BY IP_address WHERE article_id = '1')
I only post it so others could compare it to the better solution already posted that uses COUNT(DISTINCT IP_address) and see how one is different from the other.
If there is a better way to use GROUP BY for the same task, I am yet to learn it.
SELECT IP, COUNT(IP) FROM ARTICLES WHERE ARTICLE_ID = '1' GROUP BY IP
Related
Suppose I have two tables, users and posts. Posts has the following fields, userid, postid, etc and userid can appear multiple times as one user can write multiple posts....I'm just trying sort the users table based off the # of occurrences per userid in the posts table. I can get the # of occurrences per user using this
SELECT userid, COUNT(*)
FROM posts
GROUP BY userid;
I would like to use the values under COUNT(*) column, maybe add it to my other table because then I can simply to something like this
SELECT * FROM users
ORDER BY newcolumn ASC;
but I'm having trouble doing that. Or can I do it without having to add an extra column? Hints please. Thanks
Left join is the key here!
SELECT users.userid,count(posts.userid) AS total_count
FROM users
LEFT JOIN posts on posts.userid = users.userid
GROUP BY users.userid
ORDER BY total_count DESC;
We are taking the left join on two tables with same user_id and we are counting the total number of posts per user using group by. Finally sort by count and show results.
try an left join:
select users.userid, [user fields],count(postid) as posts_count
from users
left join posts on posts.userid = users.userid
group by users.userid,[user fields]
order by posts_count desc.
You want to select users (FROM users) but you want to sort based on criteria in another table (COUNT(*) FROM posts) -- therefore you need to use a JOIN
Off-hand I can't seem to recall if "JOIN" or "RIGHT JOIN" or "FULL JOIN" is what you need if you wanted to get a cartesian product of the tables then group and aggregate on a single field, but I can avoid the need to remember with a subquery (hopefully someone will soon post a smaller and smarter answer):
SELECT users.* FROM users
JOIN (
SELECT userid, COUNT(*) as count
FROM posts
GROUP BY userid
) as subquery ON users.id = subquery.userid
ORDER BY subquery.count
Note: I haven't tested this query, but it looks good to me. Again: hopefully someone will post a better answer soon as I'm not doing my due dilligence, but you definitely need a JOIN :)
You could add a post_count column to the users table, but you would also have to update that count column every time a user creates a new post and you would have to build that logic into your application.
Otherwise, it looks like the answer from FallAndLearn will get you what you need.
I run a survey where all answers are stored in a separate row in the 'survey' table.
My table looks like this:
(ID,user_id,Q,A)
(1,10,'laundry','oxiclean')
(2,10,'laundry','tide')
(3,10,'laundry','pods')
(4,11,'laundry','spray n wash')
(5,11,'laundry','resolve')
(6,12,'laundry','oxiclean')
(7,13,'laundry','oxiclean')
I now need to pull the count of user id that selected ONLY specific products.
"SELECT *, count(user_id) FROM survey WHERE Q='laundry' GROUP BY a"
the above will give a an overall COUNT but I need to get my count based on users that selected ONLY 'oxiclean' for example. This should return 2.
Or users that selected 'oxiclean' AND 'tide' ONLY.
How do I go about performing this 'combination' of results pulled from different rows?
Thanks a lot!
select user_id from survey group by user_id having count(user_id) = 1
This retrieves a list of users which have only one answer in the survey. Use it as a filter condition:
select q,a,count(user_id)
from survey
where a = 'oxiclean'
and user_id in (select user_id from survey group by user_id having count(user_id) = 1)
You can achieve that using a subquery, for your case it will be something like that :
SELECT *, COUNT(user_id)
FROM survey AS s
WHERE Q = 'laundry'
AND A = 'oxiclean'
AND user_id NOT IN (SELECT user_id FROM survey WHERE Q = s.Q AND A != s.A);
s.Q and s.A refer to the parent field so you don't have to reinject the name a second time.
Downside : the query works only if you want one specific answer.
If you want one query to retrieve the overall count, this one should do the trick :
SELECT A, COUNT(user_id)
FROM (
SELECT A, user_id
FROM survey
WHERE Q='laundry'
GROUP BY user_id
HAVING COUNT(user_id) = 1
) AS t
GROUP BY A
Downside : the query give only answers who have only at least one unique user_id as seen here, and this syntax create a temporary table which is something to avoid for performance reasons.
I have a MySQL table, in which I will be storing the email_id of a user along with the user's followers' email_ids. Its columns are:
ID, USER_EMAIL, FOLLWING_EMAIL
Now while the user is logged in to his account, I want to calculate:
The number of people he is following
The number of followers he has
Calculating the number of people he's following is simple:
select count(*) from list where user_email = <logged-in email>
But how can I calculate how many people are following him in just one query?
SELECT
COUNT(CASE WHEN user_email = '<email>' THEN 1 ELSE NULL END) AS following_cnt,
COUNT(CASE WHEN following_email = '<email>' THEN 1 ELSE NULL END) AS follower_cnt
FROM
list
WHERE
'<email>' IN (user_email, following_email)
I think you just need to change the field in your WHERE clause:
SELECT count(*) FROM list WHERE following_email = '...'
To count both in one query, use subselects:
SELECT
(SELECT count(*) FROM list WHERE user_email = '...') AS following,
(SELECT count(*) FROM list WHERE following_email = '...') AS followers
is there any optimize to store the data, to achieve this functionality?
Yes. Add an index on USER_EMAIL and another on FOLLOWING_EMAIL.
So is FOLLOWING_EMAIL the email address of a person this user is following? Or an index into another table? If the former, then:
SELECT COUNT(*) from list where FOLLOWING_EMAIL="test#test.com"
I am using mysql 5.0.51b.
I have one table named xyz.
xyz table has a columns abc,location,pqr and lmn
Everytime an information is sent to particular location, its entry is done in xyz table.
I want to have the name of the location to which maximum information is sent.
The way i tried:
First of all i count the number of entries sent to each location using count and group by.
Now, the problem is to have the name(s) of the location with maximum values.
I have used temporary solution:
I use order by clause and limit to get the first record that has max values.
But this has one problem
If two locations has same count then above solution will give only one location and the other with same count will not be returned.
I want to solve this problem
Any hint will be very helpful
Thanks in anticipation
Thank you very much to everyone who has responded to my question and spared time to solve my problem.
However, i have got the solution:
SELECT count( * ) AS cnt2, location
FROM sms
GROUP BY location
HAVING cnt2 = (
SELECT count( * ) AS cnt
FROM sms
GROUP BY location
ORDER BY cnt DESC
LIMIT 1 );
very important hint on http://lists.mysql.com/mysql/203074
The inner query gives you the max count and outer query compares each count with max count.
Select MAX(cnt.Total) from
(select count( Name)as Total from Gk_RegUser_answer_rel group by Reg_UserId) As cnt
Try this interesting solution -
SELECT x.* FROM xyz x
JOIN (
SELECT GROUP_CONCAT(location) locations FROM (
SELECT location, COUNT(*) cnt FROM xyz GROUP BY location ORDER BY COUNT(*)) t
GROUP BY cnt DESC
LIMIT 1
) t
ON FIND_IN_SET(x.location, t.locations);
SELECT COUNT(*), `location` FROM `xyz` GROUP BY `location`
Above query will give you the information count to a specific location.
If this is not what you were looking for, can you provide some sample data and expected output?
I have a table with User data such as name, address etc and another table which has a paragraph of text about the user. The reason that they are separate is because we need to record all the old about data. So if the user changes their paragraph - the old one should still be stored. Each bit of about data has a primary key aboutMeID. What I want to do is have a join that pulls their name, address etc and the latest bit of aboutMe data from the other table.
I am not sure though how I can order the join to only get the latest about me data.
Can someone help?
Assuming you have a column with the dateEntered field you could just say
select col1, col2, col3 from aboutme order by dateEntered desc limit 1
This will give you the row that is newest.
Where you have two tables to join, the subquery asks the table with the older paragraphs to give just the last one, ordered by date (datestamp DESC) and match it up based on your user ID. Finally the outer query limits the whole thing to just the user in question (#UserID).
SELECT name, address, aboutme
FROM users
LEFT JOIN
(SELECT aboutme FROM oldertable
WHERE aboutMeID = users.id
ORDER BY datestamp DESC
LIMIT 1)
WHERE users.id = #UserID;
you should sort it by date of change descendently and limit it to one record (LIMIT 1)
subselect variant:
select name,
address,
(select aboutme
from ABOUTTABLE
where USERDATA.userid = ABBOUTTABLE.userid order by datefield limit 1)
from USERDATA
This is rather tricky and probably would be slow but it is done through depended subquery.
SELECT name, address, aboutme.text as aboutme
FROM users
LEFT JOIN aboutme ON aboutMeID = (SELECT aboutMeID FROM aboutme
WHERE user_id = users.id
ORDER BY datestamp DESC
LIMIT 1)
Not sure is it faster than #JYelton solution, it is something you'd have to test yourself.