I have two tables:
users table
list of users
stories
list of stories - multiple stories per user
I want to know the average number of stories a user has. (not a specific user, for all users)
Expected results: 2.3 average stories per user
Tried:
select avg(w) from (select count(distinct user_id) as w from stories group by user_id) a;
above ran but didn't seem correct
also:
SELECT user_id, ( SELECT COUNT(*) FROM stories w WHERE w.user_id = u.user_id ) as TotalStories FROM user u;
returned average stories for each user, not average for overall
First you need to know the number of stories per user:
select count(s.id) as n
from users u left outer join stories s on u.id = s.user_id
group by u.id
Then just apply avg to that:
select avg(n)
from (
select count(s.id) as n
from users u left outer join stories s on u.id = s.user_id
group by u.id
) as dt
SELECT COUNT(userid) AS totalusers, SUM(storycount) AS totalstories, SUM(storycount) / COUNT(userid) AS average_stories
FROM (
SELECT users.id AS userid, COUNT(stories.id) AS storycount
FROM users
LEFT JOIN stories ON (users.id = stories.user_id)
GROUP BY users.id
) AS child
Inner query does the per-user story counting. Outer query counts the total users, total stories, and the stories per user average.
Related
I've created a query that finds the users of a specific site that have liked every photo on the site and stand out as potential bots.
I'm trying to count the number of bots.
My query currently returns all the bot usernames and the number of photos that they've liked, but I'm having trouble simply counting them.
It would be ideal to be able to COUNT(*) on the table that the below query generates.
SELECT
username,
COUNT(*) AS total_likes
FROM users
JOIN likes
ON likes.user_id = users.id
GROUP BY likes.user_id
HAVING total_likes = (SELECT COUNT(*) FROM photos);
You can do this with a subquery:
SELECT COUNT(*) as num_potential_bots
FROM (SELECT u.username, COUNT(*) AS total_likes
FROM users u JOIN
likes l
ON l.user_id = u.id
GROUP BY l.user_id
HAVING total_likes = (SELECT COUNT(*) FROM photos)
) u;
I have a database of users (id, name) which is connected to database of their purchases (id, userId, price).
What I want to do is to find all users who didn't make a purchase with price 500. At first I though about such query, but it would return all rows where price is not 500, not the users themselves.
select * from purchase p
join user u on u.id = p.userId
and price != 500
Does somebody have an idea how to group it so only the users who NEVER did 500 purchase would show up?
One way is to group by the user and take only those groups having no purchase with a price of 500
select u.id, u.name
from user u
left join purchase p on u.id = p.userId
group by u.id, u.name
having sum(p.price = 500) = 0
I need to count the amount of users that have have answered all of those 3 profile_options (so they have at least 3 records in the profile_answers table).
SELECT COUNT(DISTINCT(users.id)) users_count
FROM users
INNER JOIN profile_answers ON profile_answers.user_id = users.id
WHERE profile_answers.profile_option_id IN (37,86,102)
GROUP BY users.id
HAVING COUNT(DISTINCT(profile_answers.id))>=3
The problem is that this query is return a table with rows for each user and how many they answered (in this case always 3). What I need is to return just one row that has the total number of users (so the sum of all rows of this example)
I know how to do it with another subquery but the problem is that I am running into "Mysql::Error: Too high level of nesting for select"
Is there a way to do this without the extra subquery?
SELECT SUM(sum_sub.users_count) FROM (
(SELECT COUNT(DISTINCT(users.id)) users_count
FROM users
INNER JOIN profile_answers ON profile_answers.user_id = users.id
WHERE profile_answers.profile_option_id IN (37,86,102)
GROUP BY users.id
HAVING COUNT(DISTINCT(profile_answers.id))>=3)
) sum_sub
Please give this query a shoot
SELECT COUNT(DISTINCT(u.id)) AS users_count
FROM users AS u
INNER JOIN (
SELECT user_id, COUNT(DISTINCT profile_option_id) AS total
FROM profile_answers
WHERE profile_option_id IN (37,86,102)
GROUP BY users.id
HAVING COUNT(DISTINCT profile_option_id) = 3
) AS a ON a.user_id = u.id
If you have lots of data in your tables, you will get a better/faster performance by using temporary tables like so
CREATE TEMPORARY TABLE a (KEY(user_id)) ENGINE = MEMORY
SELECT user_id, COUNT(DISTINCT profile_option_id) AS total
FROM profile_answers
WHERE profile_option_id IN (37,86,102)
GROUP BY users.id
HAVING COUNT(DISTINCT profile_option_id) = 3;
Then your final query will look like this
SELECT COUNT(DISTINCT(u.id)) as users_count
FROM a
INNER JOIN on a.user_id = u.id
Unless there is a need to join the users table you can go with this
SELECT COUNT(*) AS users_count
FROM (
SELECT user_id, COUNT(DISTINCT profile_option_id) AS total
FROM profile_answers
WHERE profile_option_id IN (37,86,102)
GROUP BY users.id
HAVING COUNT(DISTINCT profile_option_id) = 3
) AS a
Should you need another solution, please consider providing us you EXPLAIN EXTENDED for the query and the table definitions along with a better problem description.
I hope this helps
You can give the queries a name using the AS clause. See the updated query below.
SELECT SUM(sum_sub.users_count) FROM (
(SELECT COUNT(DISTINCT(users.id)) as users_count
FROM users
INNER JOIN profile_answers ON profile_answers.user_id = users.id
WHERE profile_answers.profile_option_id IN (37,86,102)
GROUP BY users.id
HAVING COUNT(DISTINCT(profile_answers.id))>=3)
) as sum_sub
You should not group by on a field not present in select statement.
select id, count(*) from users group by id is fine
select count(id) from users group by id is NOT
Regarding your query I think the link to user table is not necessary. Just using foreign key should be fine.
Try this one:
select count(*) from
(SELECT users_id count(*) as cnt
FROM profile_answers
INNER JOIN users ON profile_answers.user_id = users.id
WHERE profile_answers.profile_option_id IN (37,86,102)
group by users_id
having count(*) >3)
I have three tables:
users: id, name
shifts: id, date_start, date_end
users_shifts: user_id, shift_id
I want to get all the users who have done n shifts in a specific date range, where n can be any integer (also 0!).
I can get all the users with the number of shifts they have done like this:
SELECT
users.*,
COUNT(users_shifts.user_id) AS nr_shifts
FROM
users
LEFT JOIN
users_shifts ON users.id = users_shifts.user_id
GROUP BY
users.id
I have no clue how to:
1) add the date range to this query
2) limit the results to a specific nr_shifts
Any help is greatly appreciated.
SELECT
users.*,
COUNT(users_shifts.user_id) AS nr_shifts
FROM
users
LEFT JOIN
users_shifts ON users.id = users_shifts.user_id
WHERE shifts.date_end = '10/OCT/2012'
GROUP BY
users.id
Order by users.id
LIMIT 10
A second join doesn't do what you need?
SELECT
users.*,
COUNT(users_shifts.user_id) AS nr_shifts
FROM
users
LEFT JOIN
users_shifts ON users.id = users_shifts.user_id
LEFT JOIN
shifts ON shifts.id = users_shifts.shift_id
WHERE
shifts.date_start BETWEEN 2013-06-01 and 2013-06-30
OR ISNULL(shifts.date_start)
GROUP BY
users.id
i have users table and i have posts table i want select from users the top users that have the big amount of posts from posts table and order them by numbers of posts
i can make it by array_count_values() by i cant order it
now i think if i make it by one mysql query by left and join will be more better
table structure
posts
id | auther_id
i tried this
SELECT COUNT(1) cnt, u.user_id
FROM users u
LEFT JOIN posts p
ON p.author_id=u.user_id
GROUP BY u.user_id
ORDER BY cnt DESC
LIMIT 20
it gave me this
alt text http://img511.imageshack.us/img511/6707/31154352.gif
see the arrow
what is this
i just have 2 posts under user_id 5
what is this first row
You need to aggregate the posts by user using GROUP BY u.user_id, get a COUNT value for the number of posts and ORDER BY that number, in descending order:
SELECT COUNT(1) cnt, u.user_id
FROM users u
LEFT JOIN posts p
ON p.author_id=u.user_id
GROUP BY u.user_id
ORDER BY cnt DESC
LIMIT 20
SELECT u.user_id, COUNT(*) as post_count
FROM users u
INNER JOIN posts p
USING (user_id)
GROUP BY u.user_id
ORDER BY post_count
i used this and its worked
is it true
SELECT COUNT( 1 ) cnt, a.auther_id
FROM `posts` a
LEFT JOIN users u ON a.auther_id = u.id
GROUP BY a.auther_id
ORDER BY cnt DESC
LIMIT 20