I have got the following table where if more than 1 row contain the same 'user_badge_name' and the 'user_email', the are considered duplicates.
user_id | user_name | user_badge_name | user_email
--------------------------------------------------
234 | Kylie | ky001 | kylie#test.com
235 | Francois | FR007 | france#test.com
236 | Maria | MA300 | Marie#test.com
237 | Francine | FR007 | france#test.com
I need to display the user_ids and username of those rows where 'user_badge_name' and 'user_email' are replicated.
I tried the following sql but it is not returning all user_ids, only the first id
SELECT user_id, username , COUNT(user_badge_name) AS user_badge_name_Count FROM user GROUP BY user_badge_name HAVING user_badge_name_Count > 1
Any suggestion is most appreciated
select a.user_id, a.user_name
from user as a
inner join
(SELECT user_badge_name, user_email
FROM user
GROUP BY user_badge_name, user_email
HAVING count(*)>1
) as dups
on a.user_badge_name=dups.user_badge_name and a.user_email=dups.user_email
order by a.user_badge_name, a.user_email
If you want to see all of the user ids in the same row, then you can used a GROUP_CONCAT:
SELECT GROUP_CONCAT(user_id) AS user_ids, GROUP_CONCAT(username) AS usernames, COUNT(user_badge_name) AS user_badge_name_Count FROM user GROUP BY user_badge_name HAVING user_badge_name_Count > 1
That will give you something like this:
user_ids | usernames | user_badge_name_Count
-----------------------------------------------
235,237 | Francois,Francine | 2
Related
I want to remove all duplicates where combination of first name and last name is same
table users
mysql> select * from users;
+----+------------+-----------+
| id | LastName | FirstName |
+----+------------+-----------+
| 1 | Kowalski | Jan |
| 2 | Malinowski | Marian |
| 3 | Malinowski | Marian |
| 4 | Kowalski | Jan |
| 5 | Malinowski | Marian |
| 6 | Malinowski | Marian |
+----+------------+-----------+
I've created script
set #x = 1;
set #previous_name = '';
DELETE FROM users where id IN (SELECT id from (
select id, #previous_name,IF (CONCAT(FirstName, LastName) = #previous_name, #x:= #x + 1, IF(#previous_name:=CONCAT(FirstName, LastName), #x, IF(#x:=1, #x, #x))) as occurance
from users order by CONCAT(FirstName, LastName)
) AS occurance_table where occurance_table.occurance > 1);
but sql returns error
ERROR 1292 (22007): Truncated incorrect DOUBLE value: 'JanKowalski'
I found a few similar questions, but solution were remove and word form syntax.
I want to prepare db for adding unique constrain for 2 columns, so I want to clear table from duplications.
What is best way to reach it?
I tried with the query mentioned in Answer section.
I believe that does not work. Instead I have modified the query to work
DELETE FROM users
WHERE id NOT IN
(
SELECT MIN(a.id)
FROM (SELECT * FROM users) a
GROUP BY a.LastName, a.FirstName
)
Please do correct me if I am wrong. #juergen
There is no need for a script. A single query is enough:
delete u1
from users u1
left join
(
select min(id) as min_id
from users
group by LastName, FirstName
) u2 on u1.id = u2.min_id
where u2.min_id is null
The subselect gets the lowest user id for each unique set of name. Joining to that you can delete everything else.
I have a table in MySQL which looks like this.
+---------+------------+--------------+
| user_id | key | value |
+---------+------------+--------------+
| 1 | full_name | John Smith |
+---------+------------+--------------+
| 1 | is_active | 1 |
+---------+------------+--------------+
| 1 | user_level |Administrator |
+---------+------------+--------------+
I need to get value of key full_name where user_id is 1, but only if value of key is_active is 1. I can do it with 2 separate queries, but I would like to know if it is possible to do it in a single query.
Note: I cannot change the structure of the table.
One method is to use joins:
select tn.value
from t tn join
t ta
on tn.user_id = ta.user_id and ta.key = 'active'
where tn.key = 'fullname';
i think you need below query by using exists
select t.value from your_table t where
exists ( select 1 from your_table t1
where t1.user_id=t.user_id
and t1.key='is_active'
) and t.key='full_name'
DEMO IN MYSQL 8
value
john smith
I have a following setup:
---------------------
| user_id | list_id |
---------------------
| 1 | 1 |
| 1 | 2 |
| 2 | 2 |
| 3 | 2 |
---------------------
I need to select user_id's by list_id, but only those which are unique in the table. So, in my example it should be only user_id's 2 and 3.
What should I add to
select user_id from table where list_id=2 ?
Please help, I'm really stuck...
Thanks
Group by the user_id and take only those having at least one list_id = 2 and in total only one record of this user_id
select user_id
from table
group by user_id
having sum(list_id = 2) > 0
and count(*) = 1
Try this:
select user_id from table group by user_id having count(*) =1
We can use below query
select user_id ,count(*)
from table
GROUP BY
user_id
HAVING
COUNT(*) = 1
select user_id from table group by user_id having count(*)=1;
I have two tables: contacts and client_profiles. A contact has many client_profiles, where client_profiles has foreign key contact_id:
contacts:
mysql> SELECT id,first_name, last_name FROM contacts;
+----+-------------+-----------+
| id | first_name | last_name |
+----+-------------+-----------+
| 10 | THERESA | CAMPBELL |
| 11 | donato | vig |
| 12 | fdgfdgf | gfdgfd |
| 13 | some random | contact |
+----+-------------+-----------+
4 rows in set (0.00 sec)
client_profiles:
mysql> SELECT id, contact_id, created_at FROM client_profiles;
+----+------------+---------------------+
| id | contact_id | created_at |
+----+------------+---------------------+
| 6 | 10 | 2014-10-09 17:17:43 |
| 7 | 10 | 2014-10-10 11:38:01 |
| 8 | 10 | 2014-10-10 12:20:41 |
| 9 | 10 | 2014-10-10 12:24:19 |
| 11 | 12 | 2014-10-10 12:35:32 |
+----+------------+---------------------+
I want to get the latest client_profiles for each contact. That means There should be two results. I want to use subqueries to achieve this. This is the subquery I came up with:
SELECT `client_profiles`.*
FROM `client_profiles`
INNER JOIN `contacts`
ON `contacts`.`id` = `client_profiles`.`contact_id`
WHERE (client_profiles.id =
(SELECT `client_profiles`.`id` FROM `client_profiles` ORDER BY created_at desc LIMIT 1))
However, this is only returning one result. It should return client_profiles with id 9 and 11.
What is wrong with my subquery?
It looks like you were trying to filter twice on the client_profile table, once in the JOIN/ON clause and another time in the WHERE clause.
Moving everything in the where clause looks like this:
SELECT `cp`.*
FROM `contacts`
JOIN (
SELECT
`client_profiles`.`id`,
`client_profiles`.`contact_id`,
`client_profiles`.`created_at`
FROM `client_profiles`
ORDER BY created_at DESC
LIMIT 1
) cp ON `contacts`.`id` = `cp`.`contact_id`
Tell me what you think.
Should be something like maybe:
SELECT *
FROM `client_profiles`
INNER JOIN `contacts`
ON `contacts`.`id` = `client_profiles`.`contact_id`
GROUP BY `client_profiles`.`contact_id`
ORDER BY created_at desc;
http://sqlfiddle.com/#!2/a3f21b/9
You need to prequery the client profiles table grouped by each contact.. From that, re-join to the client to get the person, then again to the client profiles table based on same contact ID, but also matching the max date from the internal prequery using max( created_at )
SELECT
c.id,
c.first_name,
c.last_name,
IDByMaxDate.maxCreate,
cp.id as clientProfileID
from
( select contact_id,
MAX( created_at ) maxCreate
from
client_profiles
group by
contact_id ) IDByMaxDate
JOIN contacts c
ON IDByMaxDate.contact_id = c.id
JOIN client_profiles cp
ON IDByMaxDate.contact_id = cp.contact_id
AND IDByMaxDate.maxCreate = cp.created_at
I have a MySQL table which has three columns:
Userid | Email | Points
---------------------------------------------------------
1 | jdoe#company.com | 20
2 | jdoe%40company.com | 25
3 | rwhite#company.com | 14
4 | rwhite%40company.com| 10
What I want to do is to delete duplicate email and merge points. I want my table to look like this:
Userid | Email | Points
---------------------------------------------------------
1 | jdoe#company.com | 45
3 | rwhite#company.com | 24
How would my query look like to return my desire table?
Anyone knows how to do this ?
Thanks in advance!
Are you looking for something like this?
SELECT MIN(userid) userid, email, SUM(points) points
FROM
(
SELECT userid, REPLACE(email, '%40', '#') email, points
FROM table1
) q
GROUP BY email
Output:
| USERID | EMAIL | POINTS |
|--------|--------------------|--------|
| 1 | jdoe#company.com | 45 |
| 3 | rwhite#company.com | 24 |
Here is SQLFiddle demo
Now if you want to deduplicate your table in-place you can do
-- Fix emails
UPDATE table1
SET email = REPLACE(email, '%40', '#')
WHERE email LIKE '%\%40%';
-- Merge points for duplicate records
UPDATE table1 t JOIN
(
SELECT email, SUM(points) points
FROM table1
GROUP BY email
HAVING COUNT(*) > 1
) q ON t.email = q.email
SET t.points = q.points;
-- Delete all duplicate records except ones with lowest `userid`
DELETE t
FROM table1 t JOIN
(
SELECT MIN(userid) userid, email
FROM table1
GROUP BY email
HAVING COUNT(*) > 1
) q ON t.email = q.email
WHERE t.userid <> q.userid;
Here is SQLFiddle demo
Use this query assuming you want to match email as is without any modification
SELECT MIN(user_id), SUM(points)as points, email FROM table_name GROUP BY email