Как использовать MAX в MySQL? - PullRequest
2 голосов
/ 05 октября 2011

Допустим, следующая таблица / данные:

person_id  age  gender  name
1          25   Female  Jane
2          28   Male    John
3          29   Female  Jill
4          24   Male    Jack

Как запросить самых старых мужчин и женщин?

Это не работает: SELECT person_id, max(age), gender, name FROM person GROUP BY gender

как он возвращает:

person_id  age  gender  name
2          28   Male    John
1          29   Female  Jane

Желаемый результат:

person_id  age  gender  name
2          28   Male    John
3          29   Female  Jill

Что не так с моим SQL?

Ответы [ 4 ]

3 голосов
/ 05 октября 2011

При выборе значения GROUP BY пол вы не можете контролировать, какое значение из каждой группы выбрано для неагрегированных столбцов (age агрегировано, но name нет):

Из документы:

MySQL extends the use of GROUP BY so that the select list can refer to
nonaggregated columns not named in the GROUP BY clause.... The server is free
to choose any value from each group, so unless they are the same, the values
chosen are indeterminate.

Однако можно получить желаемый результат с помощью подвыбора:

SELECT p1.*
FROM person p1
INNER JOIN (
    SELECT gender,MAX(age) as age
    FROM person 
    GROUP BY gender) as p2
ON p1.gender = p2.gender AND p1.age = p2.age
3 голосов
/ 05 октября 2011

Вы можете получить все данные строки, объединяющие ORDER BY и LIMIT 1.В вашем случае, используйте это дважды и в сочетании с UNION:

  ( SELECT * 
    FROM person 
    WHERE gender = 'Male'
    ORDER BY age DESC
    LIMIT 1
  )
UNION ALL
  ( SELECT * 
    FROM person 
    WHERE gender = 'Female'
    ORDER BY age DESC
    LIMIT 1
  )

Другой способ - определить максимальный возраст мужчин и женщин (с подзапросами):

SELECT *
FROM person
WHERE ( gender = 'Male'
      AND age =  
          ( SELECT MAX(age) 
            FROM person 
            WHERE gender = 'Male'
          )
      )
   OR ( gender = 'Female'
      AND age =  
          ( SELECT MAX(age) 
            FROM person 
            WHERE gender = 'Female'
          )
      )

Если у вас более двух родов или вы предпочитаете не задавать жесткие константы Male и Female в запросе, это можно переписать так:

SELECT p.*
FROM person AS p
  JOIN
      ( SELECT gender
             , MAX(age) AS maxage 
        FROM person 
        GROUP BY gender
      ) AS pg
    ON  pg.gender = p.gender
    AND pg.maxage = p.age

Вышеуказанные запросы имеютглавное отличие1-й даст вам только один мужчина и только один женский результат (максимум).2-й и 3-й запрос даст вам более одного, если есть много (мужчин) с одинаковым максимальным возрастом и аналогично для женщин.

Индекс на (gender, age) поможет любому запросу.

1 голос
/ 05 октября 2011

Вы должны добавить ORDER BY age DESC раньше, так как группировка примет первый элемент для передачи.

(я думаю, что вы могли бы даже заменить max(age) на age этим)

0 голосов
/ 05 октября 2011

Вы сказали в комментарии:

By the way, the example I gave is a simplified version of my problem. The real
problem is that I have a certain entity in my database that makes log entries. I
need to find the very last log entry for that entity. I have a timestamp column
in the table

Попробуйте следующее, должно работать в таблице, я думаю, у вас есть ... однако предоставление структуры таблицы поможет, и это может быть решено с помощью группытоже:)

select * from log_table
where log_date_time = (select max(log_date_time) from log_table)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...