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"
Related
I already have a table, "table_one", set up on phpMyAdmin that has the following columns:
USER_ID: A discord user ID (message.author.id)
USER_NAME: A discord username (message.author.name)
USER_NICKNAME: The user's display name on the server (message.author.display_name)
TIMESTAMP: A datetime timestamp when the message was entered (message.created_at)
MESSAGE CONTENT: A cleaned input keyword to successful completion of content, just for this example consider "apple" or "orange" as the two target keywords.
What I'd like as a result is a view or query that returns a table with the following:
The user's most recent display name (USER_NICKNAME), based off the most recent timestamp
The total number of times a user has entered a specific keyword. Such as confining the search to only include "apple" but not instances "orange"
My intention is that if a user entered a keyword 10 times, then changed their server nickname and entered the same keyword 10 more times, the result would show their most recent nickname and that they entered the keyword 20 times in total.
This is the closest I have gotten to my desired result so far. The query correctly groups instances where user has changed their nickname based on the static discord ID, but I would like it to retain this functionality while instead showing the most recent USER_NICKNAME instead of a USER_ID:
SELECT USER_ID, COUNT(USER_ID)
FROM table_one
WHERE MESSAGE_CONTENT = 'apple'
GROUP BY USER_ID
I don't think there is an uncomplicated way to do this. In Postgres, I would use the SELECT DISTINCT ON to get the nickname, but in MySQL I believe you are limited to JOINing grouped queries.
I would combine two queries (or three, depending how you look at it).
First, to get the keyword count, use your original query:
SELECT USER_ID, COUNT(USER_ID) as apple_count
FROM table_one
WHERE MESSAGE_CONTENT = 'apple'
GROUP BY USER_ID;
Second, to get the last nickname, group by USER_ID without subsetting rows and use the result as a subquery in a JOIN statement:
SELECT a.USER_ID, a.USER_NICKNAME AS last_nickname
FROM table_one a
INNER JOIN
(SELECT USER_ID, MAX(TIMESTAMP) AS max_ts
FROM table_one
GROUP BY USER_ID) b
ON a.USER_ID = b.USER_ID AND TIMESTAMP = max_ts
I would then JOIN these two, using a WITH statement to increase the clarity of what's going on:
WITH
nicknames AS
(SELECT a.USER_ID, a.USER_NICKNAME AS last_nickname
FROM table_one a
INNER JOIN
(SELECT USER_ID, MAX(TIMESTAMP) AS max_ts
FROM table_one
GROUP BY USER_ID) b
ON a.USER_ID = b.USER_ID AND TIMESTAMP = max_ts),
counts AS
(SELECT USER_ID, COUNT(USER_ID) AS apple_count
FROM table_one
WHERE MESSAGE_CONTENT = 'apple'
GROUP BY USER_ID)
SELECT nicknames.USER_ID, nicknames.last_nickname, counts.apple_count
FROM nicknames
INNER JOIN counts
ON nicknames.USER_ID = counts.USER_ID;
I'm trying to check and order my users table who has the most origins (referals).
I have a users table, which has an 'origin' column, filled in with another users 'username' column if they refereed them, null if nobody.
Here is what I have so far, but its constantly returning 0 for the origin_count column?
SELECT username,
(SELECT COUNT(*)
FROM users
WHERE origin = username) AS origin_count
FROM users
WHERE tmp_allow_share = 1 AND approved_at IS NOT NULL;
SELECT COUNT(*) FROM users WHERE origin = username counts how many users have themselves as origin.
What you want to do is group by username and count origin (possibly distinct if you're looking for unique referals).
SELECT COUNT(origin) FROM users GROUP BY username;
You don't need a subquery to calculate origin count, rather use count directly with group by
SELECT username,
count(*) AS origin_count
FROM users
WHERE tmp_allow_share = 1
AND approved_at IS NOT NULL
GROUP BY username;
I'm struggling to figure out how I can check for two things from one table without making two calls to mysql.
I have a Members table. I'd like to test whether a certain value exists in the MemberID column, and whether a certain value exists in the PhoneNumber column. MemberID and PhoneNumber are both indexed.
But there's something wrong with the syntax I'm trying. For example, each of
SELECT COUNT(1) AS IDExists FROM Members WHERE MemberID = '999999999999' LIMIT 1
and
SELECT COUNT(1) AS PhoneExists FROM Members WHERE PhoneNumber = '5555555555' LIMIT 1
works. Why can't they be combined, somehow, like
SELECT (COUNT(1) AS IDExists FROM Members WHERE MemberID = '999999999999' LIMIT 1), (COUNT(1) AS PhoneExists FROM Members WHERE PhoneNumber = '5555555555' LIMIT 1)
?
Or perhaps, since I only care whether the value occurs zero times, or at all, something like
SELECT EXISTS (SELECT 1 FROM Members WHERE MemberID = '999999999999')
?
But, unfortunately, there's something wrong with that syntax even for the case of one of my inquiries.
Any suggestions on how to accomplish this?
You want a conditional SUM
SQL FIDDLE
SELECT
SUM( CASE
WHEN PhoneNumber = '5555555555' THEN 1
ELSE 0
END) PhoneExists,
SUM( CASE
WHEN MemberID = '999999999999' THEN 1
ELSE 0
END) IDExists
FROM Members
You can combine two working query like this:
select a.IDExists, b.PhoneExists
from (SELECT COUNT(1) AS IDExists FROM Members WHERE MemberID = '999999999999' LIMIT 1) a,
(SELECT COUNT(1) AS PhoneExists FROM Members WHERE PhoneNumber = '5555555555' LIMIT 1) b
Though the query join two results with cartesian product, it is guaranteed that each result has only one row, it would not be a problem.
I'm not sure how big is the table and what kinds of index it has. If the table is big, then perhaps you have indexes on column MemberID and PhoneNumber respectively, then the above query will return the result quickly.
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 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