#mysql #sql
Вопрос:
Предположим, существует следующая таблица:
id B C D
1 2 3 4
1 2 4 3
2 1 2 4
2 3 1 5
Для каждого идентификатора я хочу сохранить строку с максимальным значением B, если B равно, то сохраните строку с максимальным значением C. Таким образом, конечный результат таков,
id B C D
1 2 4 3
2 3 1 5
как это реализовать с помощью SQL?
Комментарии:
1. какую версию mysql вы используете ?
2. mysql версии 5.6
3. Обязательно ли вам работать с такой старой версией? Вы не можете обновить? Такие задачи гораздо проще решаются с MySQL 8.
4. Версия не может быть изменена бизнес-командой, поскольку управление БД находится на уровне предприятия.
Ответ №1:
Максимальные задачи могут быть решены с NOT EXISTS
помощью . Вам нужны только строки, для которых не существует строки с тем же идентификатором и большим B или с тем же B и более высоким C.
select *
from mytable t1
where not exists
(
select null
from mytable t2
where t2.id = t1.id
and
(
t2.b > t1.b
or
(t2.b = t1.b and t2.c > t1.c)
)
);
Начиная с MyQL 8 , мы можем просто ранжировать наши строки с RANK
DENSE_RANK
помощью или ROW_NUMBER
вместо этого:
select id, b, c, d
from
(
select id, b, c, d, row_number() over (partition by id order by b desc, c desc) as rn
from mytable
) t
where rn = 1;
Демо: https://dbfiddle.uk/?rdbms=mysql_8.0amp;fiddle=a54a906373e0dd00a2fb42c119186dd3
Ответ №2:
Поскольку вы используете 5.6, поэтому функция ранга там работать не будет. Попробуйте следующий подход
select id, B, C, D
FROM
(
select id, B, C, D,
@order_id := IF(@current_id = id,
@order_id 1, 1) AS order_id,
@current_id := id
from Test
order by id asc, B desc, C DESC
) T WHERE order_id=1
Ответ №3:
Подходы Торстена прекрасны. Другой метод заключается в использовании кортежей для сопоставления строк:
select t.*
from t
where (t.b, t.c) = (select t2.b, t2.c
from t t2
where t2.id = t.id
order by t2.b desc, t2.c desc
limit 1
);