Mysql - getting distinct records - mysql

I have the following MySql table (user_actions) with the following columns:
id, user_id, created_at, action_type
I want a sql query that will get the latest actions that the user performed with no duplication of the actions.
for example:
user_id 1 has 3 records that has the action_type "follow"
and 2 records that has the action_type "unfollow"
in this case i want the query to return two records, one with action_type "follow" and one with "unfollow"
any thoughts?

You can use SQL's group by clause for this:
select user_id, action_type, max(created_at)
from user_actions
group by user_id, action_type

try this:
select ua.*
from user_actions ua
join (select max(id) as max_id,user_id,action_type from user_action group by user_id,user_action) ua_max
on ua.id=ua_max.max_id and ua.user_id=ua_max.user_id and ua.action_type=ua_max.action_type

Try this query:
select * from user_actions where action_type, created_at in
(select action_type, max(created_at) from user_actions group by action_type);

Related

How to exclude specific duplicates from MySQL group_by dataset?

I'm using MySQL 5.7.12. I have a simple query that looks like the following:
SELECT COUNT(id) as count, pic_id
FROM user_pictures
GROUP BY pic_id
I would like to exclude all the duplicate USER_ID records from grouping. So I did the following, however, it's not returning any result:
SELECT COUNT(id) as count, pic_id
FROM user_pictures
GROUP BY pic_id
HAVING count(user_id) = 1
What am I missing here?
Use DISTINCT so it doesn't count duplicates of the same user_id:
SELECT COUNT(id) as count, pic_id
FROM user_pictures
GROUP BY pic_id
HAVING count(DISTINCT user_id) = 1

Ignore duplicates on GROUP BY

I have a table containing a shop_id, name and promotion_code. I want to get the amount of records for every shop_id, but there are some duplicate records where a promotion_code is used multiple times. I want to ignore these.
I have tried:
SELECT shop_id, count(*) as total_entries FROM tbl GROUP BY shop_id
This gives me the correct structure, but it does count all the duplicate rows. So I thought I'd try grouping them first on promotion_code, and then on shop_id:
SELECT shop_id, count(*) as total_entries FROM tbl GROUP BY promotion_code, shop_id
But this gives me all zero's as result.
SELECT shop_id, count(distinct promotion_code) as total_entries FROM tbl GROUP BY shop_id
try :
select shop_id, count(distinct promotion_code)
from tbl
group by shop_id
SELECT shop_id, count(*) as total_entries FROM tbl GROUP BY promotion_code, shop_id
Instead of using (*) you could use DISTINCT function so that you will be sure that all data you try to group are all unique values.
You could do something like this:
SELECT shop_id, COUNT(DISTINCT promotion_code) as total_entries FROM tbl GROUP BY shop_id

Mysql most outer table visibility in nested loops

Let's assume i have 4 tables:
'users' (id, username),
'photos' (id, user_id, name),
'photos_comments' (id, photo_id, user_id, text),
'photos_likes' (id, photo_id, user_id, test).
I want to calculate sum of all comments and likes for every user in all of his uploaded photos. For that i'm trying to build a query:
SELECT users.*,
(SELECT SUM(count) as rating FROM(
SELECT COUNT(*) as count FROM photos_likes
WHERE photos_likes.photo_id IN (SELECT photos.id FROM photos WHERE photos.user_id = users.id)
UNION
SELECT COUNT(*) as count FROM photos_comments
WHERE photos_comments.photo_id IN (SELECT photos.id FROM photos WHERE photos.user_id = users.id)
) as total_rating) as rating FROM users
It returns 'Unknown users.id column in WHERE clause' error. So it looks like it can't see users table in most inner query.I can't understand why it happens,because another similar query works ok:
SELECT users.*,
(SELECT COUNT(*) as count FROM photos_likes
WHERE photos_likes.photo_id IN (SELECT photos.id FROM photos WHERE photos.user_id = users.id)) as likes_count,
(SELECT COUNT(*) as count FROM photos_comments
WHERE photos_comments.photo_id IN (SELECT photos.id FROM photos WHERE photos.user_id = users.id)) as comments_count FROM users
In this query it can grab id from users table row in most inner query. Why is it working like that? Thanks for help.
Look into Subqueries in the FROM Clause:
Subqueries in the FROM clause cannot be correlated subqueries, unless used within the ON clause of a JOIN operation.
In your second example, you use the subquery in a where clause. That's the difference.
See also Correlated Subqueries.
select
photos.userid,
photos.photoid,
count(distinct commentid),
count(distinct likeid),
count(distinct commentid) + count(distinct likeid) as total
from
photos
left join photos_comments on photos.photoid=photos_comments.photoid
left join photos_likes on photos.photoid=photos_likes.photoid
group by photos.userid, photos.photoid

Select the max value from two tables

I have a query like this, to select the most recent time someone was contacted:
SELECT `user_id`, `last_contact`
FROM `emails_sent`
group by `user_id`
order by `last_contact` desc
The above code gives a table with the last contact time for each user. Now, I have another table with contacts to users, a table with columns user_id and last_contact, among others.
How can I make my select use both tables and select the last contact time for each user from the two tables?
Summarize the union of two summary queries, something like this.
SELECT user_id,
MAX(user_date) user_date
FROM
(
SELECT user_id,
MAX(last_contact) user_date
FROM emails_sent
GROUP BY user_id
UNION ALL
SELECT whatever_user_id_column user_id,
MAX(whatever_date_column) user_date
FROM whatever_table
GROUP BY user_id
)a
GROUP BY user_id

How to find most repeating element from a table?

I have a table tbl_user and I want to find which user_name(s) have the most repeating values in the table. I only want to retrieve those user_id(s).
I also need a separate query to find the count the of duplicate user_name(s) in the table .
First query to find the biggest amount of repeated usernames:
SELECT user_name, COUNT(user_id) AS amount
FROM tbl_user
GROUP BY user_name
ORDER BY amount DESC
And then grab id`s:
# faster way using username from last query
SELECT user_id
FROM tbl_user
WHERE user_name = '$user_name'
# longer way
SELECT user_id
FROM tbl_user
WHERE user_name = (
SELECT user_name
FROM tbl_user
GROUP BY user_name
ORDER BY COUNT(amount) DESC
LIMIT 1
)
To find the count of duplicates:
SELECT count(id) AS num_duplicates FROM tbl_users GROUP BY user_name ORDER BY num_duplicates DESC
To find the user_id's of the most duplicated user_name:
SELECT user_id FROM tbl_user
WHERE username IN ( SELECT user_id
FROM tbl_users
GROUP BY user_name
ORDER BY count(id) DESC LIMIT 0, 1)
SELECT COUNT(*) FROM tbl_user
GROUP BY tbl_user.user_name
Will give you the number of duplicate user_names. You can use a scripting language to select out the highest one if you like, or just look at the list if it's not something you need automated.
If you mean you want to count the occurences of a particular username, something like this may work for you.
select user_name,user_id,count(*) as mycount from tbl_user group by user_name order by mycount desc limit 5
This should get the top 5 entries
You could select the user_names which are duplicated with this SQL:
SELECT COUNT(1) AS duplicates, user_name
FROM tbl_user
GROUP BY user_name
HAVING duplicates > 1
Having done this, you can then use it as a subquery to find out the count of duplicate user_names
SELECT COUNT(1) AS count_of_user_names, SUM(duplicates) AS duplicate_records
FROM (
SELECT COUNT(1) AS duplicates, user_name
FROM tbl_user
GROUP BY user_name
HAVING duplicates > 1
) AS subquery
Or use it to find out the user ids:
SELECT user_id
FROM tbl_user
WHERE user_name IN (
SELECT user_name
FROM tbl_user
GROUP BY user_name
HAVING COUNT(1) > 1
)