Delete partial duplicates from a MySQL table - mysql

I have a table that looks like this
Id FirstName
5 Adam
6 Bob
8 Bob
5 Carl
5 Dewie
8 Ernest
When two rows have the same Id, I'd like to keep only one of them. On this example, I would obtain
Id FirstName
5 Adam
6 Bob
8 Bob
Is there concise command to that? I was thinking of
SELECT * FROM Persons HAVING(COUNT(Id)=1)
or
SELECT DISTINCT(Id), FirstName FROM Persons
but my syntax isn't correct.

Hope you are looking for this::
SELECT * from Persons GROUP BY Id

SELECT Id, MIN(FirstName)
FROM Persons
GROUP By Id

Your DISTINCT query will also work, you just need to add GROUP BY id
SELECT DISTINCT(Id), FirstName
FROM Persons
GROUP BY id;
Demo

Related

Retrieve only the first row from each duplicate id in MySQL

I want to retrieve only the first row from each duplicate id in a table.
The issue is that every other field except the id is unique, so that means I cannot "filter" the rows.
Here is my scientist table:
id
firstname
lastname
1
albert
einstein
1
albert1
einstein1
1
albert2
einstein2
1
albert3
einstein3
2
isaac
newton
2
isaac1
newton1
3
marie
curie
3
marie1
curie1
3
marie2
curie2
Note: The firstname and the lastname are irrelevant I just want to extract the first row of each id.
And below you can find my desired output:
id
firstname
lastname
1
albert
einstein
2
isaac
newton
3
marie
curie
I have tried to GROUP BY id but it is not working.
Also, I have tried to select the scientist table based on the distinct ids of the same table
SELECT * FROM scientist WHERE id IN (SELECT DISTINCT id FROM scientist)
But then I realised that my logic was incorrect.
Try it here enter link description here
select id,firtname,lastname
from(
select *, ROW_NUMBER() OVER(PARTITION BY scientist.id) c
from scientist) t
Where c = 1

Mysql: Select all values alphabetically between two strings in a table

Okay let's say I have this in my table:
id
name
1
tom
2
anna
3
beatrice
4
robert
5
xavier
6
zoe
7
eustace
How can I select all ids of the names that are alphabetically sorted?
Say, select * from myTable where name "between" 'beatrice' and 'tom' order by name;
Should give me :
id
name
3
beatrice
7
eustace
4
robert
1
tom
Because in alphabetical order, those are in between 'beatrice' and 'tom'.
If you only want the ID's you need:
select id from myTable where name between 'beatrice' and 'tom' order by name;
Since these are strings, try this:
SELECT id
FROM tableName
WHERE nameField >= 'Landon' and nameField <= 'Peter'
ORDER BY nameField;
If you want to use the full name (first and last), you can try with that too.

MySQL count occurrences but return all rows

Im trying to count occurrences of name, but i want each row returned no matter if that name has already been counted. The data looks like;
ID | NAME
1 Peter
2 Simone
3 Otto
4 Cedric
5 Peter
6 Cedric
7 Cedric
The following only returns one row per unique name
select id, first_name, count(first_name)from table group by first_name
ID | FIRST_NAME | count(first_name)
1 Peter 2
2 Simone 1
3 Otto 1
4 Cedric 3
But im trying to return every row, something like
ID | FIRST_NAME | count(first_name)
1 Peter 2
2 Simone 1
3 Otto 1
4 Cedric 3
5 Peter 2
6 Cedric 3
7 Cedric 3
If you are using MySQL version >= 8.0, then you can use window functions:
select id,
first_name,
count(*) over (partition by first_name)
from table
For earlier versions:
select id,
first_name,
(select count(*) from table where first_name = t.first_name)
from table t
You can use a Correlated subquery:
SELECT t1.id,
t1.first_name,
(SELECT COUNT(id)
FROM table t2
WHERE t2.first_name = t1.first_name) AS total_count
FROM table t1
Edit: now that I've seen the other answers, why is joining better than using a correlated subquery? Because a correlated subquery is executed for every row in your table. When you join it, the query is executed just once.
Then you have to join those queries.
select * from
table
inner join (
select first_name, count(first_name) as name_count from table group by first_name
) qcounts on table.first_name = qcounts.first_name
Also note, that in your query you have to remove id from the select clause, since you neither have it in your group by clause nor do you apply an aggregate function on it. Therefore a random row is returned for this column.
It's a good idea to let MySQL remind you of that by activating the only_full_group_by sql mode. To do this you can do
set global sql_mode = concat(##global.sql_mode, 'only_full_group_by');

How to use IN query?

In mp_cities table city_name and city_id are the fields
city_id city
--------------------
1 Chennai
2 Bangalore
3 Kerala
In profile table
user_email city_type
------------------------------
abc#gmail.com 1,2,3
I am using the following query
SELECT city_name
FROM mp_cities
WHERE city_id IN (SELECT city_type
FROM profile
WHERE user_email='abc#gmail.com')
this query will result Chennai.
I have to get all the cities
You can use FIND_IN_SET() in MySQL.
SELECT a.*
FROM mp_cities a
INNER JOIN profile b
ON FIND_IN_SET(a.city_id, b.city_type)
WHERE b.user_email = 'abc#gmail.com'
but the best way so far I can think is to normalize the table properly.
mp_cities
city_id (PK)
city
other columns
profile
user_id (PK)
other columns
mp_cities _profile
city_id (FK)
user_id (FK)
You would get the desired result if the profile table looked like this:
user_email city_type
------------------------
abc#gmail.com 1
abc#gmail.com 2
abc#gmail.com 3
That is, the inner SELECT must return several rows, each with a number, NOT one row with a comma-delimited set of numbers.
Try to join both tables with FIND_IN_SET() function like this:
SELECT c.*
FROM mp_cities c
JOIN profile p
ON FIND_IN_SET(c.city_id,p.city_type) > 0;
See this SQLFiddle

How to group by a field and return list of other field?

I have a table with columns id, user
I want to group by column id and show a list of users (comma separated) for each id.
In the final output I need to display:
user joe - id 1
users jim, mark, john - id 2
user dave - id 3
....
I'm getting error "Cardinality violation: 1242 Subquery returns more than 1 row" if I try this:
SELECT id, (SELECT distinct(user) FROM mytable b where a.id = b.id)
FROM mytable a
GROUP BY id
Since you are using MySQL, there is a built-in function for that which is the GROUP_CONCAT function. For example, you have a records like this:
ID User
1 Joe
2 Jim
2 Mark
2 John
3 Dave
If you try to run this query:
SELECT ID, GROUP_CONCAT(User) Users
FROM tableName
GROUP BY ID
you will then have a result like this:
ID Users
1 Joe
2 Jim, Mark, John
3 Dave
What you're looking for is the GROUP_CONCAT aggregate function:
SELECT id, GROUP_CONCAT(user) FROM table GROUP BY id