简体   繁体   中英

get bad data in group by and min mysql

Im trying to get the older person in a team, im using the group by and min operators, but it not return me the correct values.

This is my example data:

table persons:

id   |  name   |  birthdate           |  team_id
-----------------------------------------
1    | person1 |  1993-09-29 15:15:15 | 1
2    | person2 |  1994-09-29 15:15:15 | 1
3    | person3 |  1992-09-29 15:15:15 | 2
4    | person4 |  1990-09-29 15:15:15 | 2

im using this query to get the older person by team:

select id, name, min(birthdate) from persons group by team_id

im expected the query return me this data:

id   |  name   |  min(birthdate)  
----------------------------
1    | person1 |  1993-09-29 15:15:15
4    | person4 |  1990-09-29 15:15:15

but it is returning this:

id   |  name   |  min(birthdate)
----------------------------
1    | person1 |  1993-09-29 15:15:15
3    | person3 |  1990-09-29 15:15:15

the birthdate is correctly returned, but the name and id are incorrect.

What is happening here? What is my error?

This works on every mysql Version.

But you didn't specify what should happen if two have the same birthday.

The second result shows you what happens with my query.

 CREATE TABLE persons ( `id` INTEGER, `name` VARCHAR(7), `birthdate` datetime, `team_id` INTEGER ); INSERT INTO persons (`id`, `name`, `birthdate`, `team_id`) VALUES ('1', 'person1', '1993-09-29 15:15:15', '1'), ('2', 'person2', '1994-09-29 15:15:15', '1'), ('3', 'person3', '1992-09-29 15:15:15', '2'), ('4', 'person4', '1990-09-29 15:15:15', '2');
\n \n\n \n
SELECT p.`id`, p.`name`, p.`birthdate`# FROM persons p INNER JOIN (select team_id, min(birthdate) minbirth from persons group by team_id) mint ON p.birthdate = mint.minbirth AND p.team_id = mint.team_id ORDER By p.team_id,p.`id`
\nid | name | birthdate          \n-: |  :------ |  :------------------ \n 1 |  person1 | 1993-09-29 15:15:15 \n 4 |  person4 | 1990-09-29 15:15:15 \n
INSERT INTO persons (`id`, `name`, `birthdate`, `team_id`) VALUES ('5', 'person5', '1993-09-29 15:15:15', '1'), ('6', 'person6', '1990-09-29 15:15:15', '2');
\n \n
SELECT p.`id`, p.`name`, p.`birthdate`# FROM persons p INNER JOIN (select team_id, min(birthdate) minbirth from persons group by team_id) mint ON p.birthdate = mint.minbirth AND p.team_id = mint.team_id ORDER By p.team_id,p.`id`
\nid | name | birthdate          \n-: |  :------ |  :------------------ \n 1 |  person1 | 1993-09-29 15:15:15 \n 5 |  person5 | 1993-09-29 15:15:15 \n 4 |  person4 | 1990-09-29 15:15:15 \n 6 |  person6 | 1990-09-29 15:15:15 \n

db<>fiddle here

This is not an aggregation query. It is a filtering query. I recommend a correlated subquery in the WHERE clause:

select p.*  -- you can select only the columns you want
from persons p
where p.birthdate = (select min(p2.birthdate)
                     from persons p2
                     where p2.team_id = p.team_id
                    );

Another very common approach is to use window functions:

select p.*
from (select p.*,
             rank() over (partition by team_id order by birthdate) as seqnum
      from persons p
     ) p
where seqnum = 1;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM