Deleting duplicate data mysql - mysql

We have duplicate id where in if we use
SELECT MAX(id), COUNT(id) AS count
FROM user_status
GROUP BY user_id, user_type
HAVING COUNT(*) > 1
we get the duplicate data
Now when I tried to insert it in delete via
DELETE
FROM user_status
WHERE id IN (SELECT MAX(id), COUNT(id) AS count
FROM user_status
GROUP BY user_id, user_type
HAVING COUNT(*) > 1
)
I got the following error
Operand should contain 1 column
How can I fix this ? TIA

As message is clear that you are selecting two columns in the subquery which is not allowed in IN clause but still mysql shows some error in such from of query so please replace the query with join as below
DELETE us
FROM user_status us
INNER JOIN (SELECT MAX(id) id
FROM user_status
GROUP BY user_id, user_type HAVING COUNT(*) > 1) t ON t.id = us.id

How about
DELETE user_status
FROM user_status LEFT JOIN (
SELECT MAX(user_id) maxId
FROM user_status
GROUP BY user_type
) a ON maxId = user_id
WHERE maxId IS NULL;
In your code where col1 in (select col1, col2) the column count simply doesn't match. If you reference each selected column, it works in principle:
DELETE FROM user_status
WHERE (user_id, user_type) NOT IN (
SELECT MAX(user_id) maxId, user_type
FROM (select * from user_status) a
GROUP BY user_type);

Related

Referring to CTE in WHERE condition of UPDATE

I'm trying to run a query like this:
WITH cte AS
(
SELECT id, category, SUM(amount) AS sum_amount FROM t1 GROUP BY id, category
)
UPDATE table SET amount = cte.sum_amount WHERE id = cte.id;
However, I keep getting the error
Unknown column 'cte.id in WHERE clause'
Does anyone know how I can refer to my common table expression in the UPDATE query, or otherwise, rewrite it?
You can try below
WITH cte AS
(
SELECT id, SUM(amount) AS sum_amount FROM t1 GROUP BY category
)
UPDATE T
SET T.sum_amount= CT.sum_amount
FROM table T
JOIN cte CT
ON T.id = CT.id
Alternate way with Temporary table, you can read about CTE and Temporary Table
Temporary table:
SELECT id, category, SUM(amount) AS sum_amount
INTO #temp
FROM t1 GROUP BY id, category
Update query with temp table:
UPDATE OT
SET OT.sum_amount= TT.sum_amount
FROM table OT
JOIN #temp TT
ON OT.id = TT.id
CTE:
WITH cte AS
(
SELECT id, category, SUM(amount) AS sum_amount FROM t1 GROUP BY id,category
)
UPDATE T
SET T.sum_amount= CT.sum_amount
FROM table T
JOIN cte CT
ON T.id = CT.id

SQL count number of common matches using several WHERE clauses

I have a table having columns like: membership_id | user_id | group_id
I'm looking for a SQL query to get the number of common groups between 2 different users. I could do that in several queries and using some PHP but I'd like to know if there is a way to use only SQL for that.
Like with the user ids 1 and 3, there are 3 common groups (1, 5 and 6) so the result returned would be 3.
I've made several tests but so far no result...Thank you.
You don't need "multiple WHERE clauses" or even a self JOIN:
SELECT group_id
FROM theTable AS t
WHERE t.user_id IN (1, 3)
GROUP BY group_id
HAVING COUNT(DISTINCT user_id) = 2;
more generically
SELECT group_id
FROM theTable AS t
WHERE t.user_id IN ([user id list])
GROUP BY group_id
HAVING COUNT(DISTINCT user_id) = [# of user ids in list];
Edit: Oh, you wanted the number of groups....
SELECT COUNT(1) FROM (
SELECT group_id
FROM theTable AS t
WHERE t.user_id IN (1, 3)
GROUP BY group_id
HAVING COUNT(DISTINCT user_id) = 2
);
You can achieve this with join.
Try this:
select t1.user_id, t2.user_id, group_concat(distinct t1.group_id)
from your_table t1
join your_table t2
on t1.user_id < t2.user_id
and t1.group_id = t2.group_id
group by t1.user_id, t2.user_id;
If you don't want a concatenated output:
select distinct t1.user_id, t2.user_id, t1.group_id
from your_table t1
join your_table t2
on t1.user_id < t2.user_id
and t1.group_id = t2.group_id;
Try to join two instances of the same table (for each of them you select only the records relative to one of the users) using group_id as join attribute, and count the result:
SELECT COUNT(*)
FROM table AS t1
JOIN table AS t2 ON t1.group_id=t2.group_id
WHERE t1.user_id=1 AND t2.user_id=3;
SELECT COUNT(*)
FROM TABLE_NAME USER_ONE_INFO
TABLE_NAME USER_TWO_INFO
WHERE USER_ONE_INFO.ID = USER_ONE_ID
AND USER_TWO_INFO.ID = USER_TWO_ID
AND USER_ONE_INFO.GROUP_ID = USER_TWO_INFO.GROUP_ID;

sql query to select the latest entry of each user

I have a location table in my database which contains location data of all the users of my system.
The table design is something like
id| user_id| longitude| latitude| created_at|
Now I have a array of user ids and I want to write a sql query to select the latest location of all these users. Can you please help me with this sql query ?
In the user_id in (......) at the end of the query you sould insert your array of user ..
select * from my_table
where (user_id , created_at) in (select user_id, max(created_at)
from my_table
group by user_id)
and user_id in ('user1','user2',... ) ;
SELECT
t1.ID,
t1.user_id,
t1.longitude,
t1.latitude,
t1.created_at
FROM
YourTable t1
INNER JOIN
(SELECT MAX(id), user_id FROM YourTable GROUP BY user_id) t2 on t2.user_id = t1.user_id
INNER JOIN
yourArrayTable ON
yourArrayTable.user_id = t1.user_id

SELECT row with MAX id from each GROUP BY (unique_id) and ORDER BY number

I have table with id, unique_id, and order_number.
I want to GROUP rows by unique_id
I want to take row with MAX id from each group
And last thing I want to sort that rows by order_number
Also I have few WHERE clauses. This is my attempt which does not work:
SELECT MAX(id) AS id
, order_number
FROM table
WHERE final = 0
AND username = '$username'
AND active = 1
GROUP
BY unique_id
ORDER
BY order_number
You can use your query as a subquery:
SELECT *
FROM table
WHERE id IN (SELECT MAX(id) AS id
FROM table
WHERE final=0 AND username='$username' AND active=1
GROUP BY unique_id)
ORDER BY order_number
or, if id is not unique, use JOIN:
SELECT t1.*
FROM table AS t1
JOIN (SELECT MAX(id) AS max_id, unique_id
FROM table
WHERE final=0 AND username='$username' AND active=1
GROUP BY unique_id
) AS t2 ON t1.unique_id = t2.unique_id AND t1.id = t2.unique_id
ORDER BY order_number
Try this:
SELECT id, redni_broj
FROM table
WHERE final=0 AND username='$username' AND active=1 AND
id IN (
SELECT MAX(id) FROM table table2
WHERE table.unique_id = table2.unique_id
)
GROUP BY unique_id
ORDER BY order_number;

remove duplicates in a column

I have the following query to basically find all duplicates in my username column:
SELECT `username`
FROM `instagram_user`
GROUP BY `username`
HAVING COUNT( * ) >1
How do I remove all the duplicates, such that it will only leave me with one unique username in the table? I don't care which entity it is that is persisted or removed, as long as there's one unique username in the table.
If you don't care what record to choose then just add a unique constraint while using IGNORE
ALTER IGNORE TABLE instagram_user ADD UNIQUE (username);
Here is SQLFiddle demo
and MySQL will do the job for you. You want to have that unique constraint anyway in order to keep your table out of duplicates in the future.
or alternatively you can do
DELETE t
FROM instagram_user t JOIN
(
SELECT username, MAX(id) id
FROM instagram_user
GROUP BY username
HAVING COUNT(*) > 1
) q
ON t.username = q.username
AND t.id <> q.id
This one will leave only a row with max id for rows that have duplicate usernames.
Here is SQLFiddle demo
Not sure this is for SQL server, you can try a similar code in mysql.
;With CteUsers AS(
SELECT *,ROW_NUMBER() OVER (PARTITION BY username Order by username) AS ROWID
FROM(
SELECT PkId, `username`
FROM `instagram_user`
)tbltemp)
SELECT * FROM CteUsers;
This will result as follow
PkId username RowId
1 xx 1
2 xx 2
....
then delete where RowId > 1
;With CteUsers AS(
SELECT *,ROW_NUMBER() OVER (PARTITION BY username Order by username) AS ROWID
FROM(
SELECT PkId, `username`
FROM `instagram_user`
)tbltemp)
DELETE instagram_user WHERE PkId iN (SELECT PkId FROM CteUsers WHERE ROWID > 1);
This will give you the duplicates (i.e. the ones you need to delete) ...
select a.id, a.username from instagram_user a, instagram_user b
where a.username = b.username and a.id <> b.id
and b.id = (select min(id) from instagram_user where username = a.username)
so the DELETE would be something like ...
delete from instagram_user where id in
(select a.id from instagram_user a, instagram_user b
where a.username = b.username and a.id <> b.id
and b.id = (select min(c.id) from instagram_user c
where c.username = a.username))