Можете ли вы получить другой столбец из строки с минимальным или максимальным значением?

#mysql

#mysql

Вопрос:

Я создаю приложение с миллионами строк, поэтому я стараюсь избегать объединения, когда это возможно. У меня есть таблица, подобная этой:

 ID        category  value_1   value_2
1         1         2.2432    5.4321
2         2         6.5423    5.1203
3         1         8.8324    7.4938
4         2         0.4823    9.8244
5         2         7.2456    3.1278
6         1         1.9348    4.4421
  

Я пытаюсь получить данные value_1 из строки с наименьшим ID и value_2 из строки с наибольшим идентификатором, сгруппированные по category , вот так:

 category  value_1   value_2
1         2.2432    4.4421
2         6.5423    3.1278
  

Возможно ли это эффективным способом, избегая таких конструкций, как операции со строками и ОБЪЕДИНЕНИЕ?

Спасибо!

Комментарии:

1. Пожалуйста, объясните, почему 6.5423 в ожидаемых результатах отображается значение категории 2. Похоже, это не соответствует вашей логике.

2. почему «избегание конструкций, таких как операции со строками и ОБЪЕДИНЕНИЕ»? это не имеет смысла

3. @TimBiegeleisen Из категории 2 наименьший идентификатор равен 2, который имеет значение 6.5423 .

4. @ysth Полная таблица содержит больше столбцов и десятки миллионов строк. Сначала я использовал несколько объединений, но это удвоило время загрузки.

Ответ №1:

Попробуйте это:

 SELECT 
    category, 
    (
        SELECT t2.value1
        FROM table1 t2
        WHERE t2.id = MIN(t1.id)
    ) as value1,
    (
        SELECT t3.value2
        FROM table1 t3
        WHERE t3.id = MAX(t1.id)
    ) as value2
FROM
    table1 t1
GROUP BY
    category
;
  

Создайте и заполните таблицу:

 CREATE TABLE `table1` (
  `id` INT NOT NULL,
  `category` INT NULL,
  `value1` DOUBLE NULL,
  `value2` DOUBLE NULL,
  PRIMARY KEY (`id`)
);
INSERT INTO table1 VALUES
(1, 1, 2.2432, 5.4321),
(2, 2, 6.5423, 5.1203),
(3, 1, 8.8324, 7.4938),
(4, 2, 0.4823, 9.8244),
(5, 2, 7.2456, 3.1278),
(6, 1, 1.9348, 4.4421);
  

Вывод:

 1   2.2432  4.4421
2   6.5423  3.1278
  

Ответ №2:

Один из подходов, который позволяет избежать объединений, заключается в использовании ROW_NUMBER :

 WITH cte AS (
    SELECT *, ROW_NUMBER() OVER (PARTITION BY category ORDER BY ID)      rn_min,
              ROW_NUMBER() OVER (PARTITION BY category ORDER BY ID DESC) rn_max
    FROM yourTable
)

SELECT
    category,
    MAX(CASE WHEN rn_min = 1 THEN value_1 END) AS value_1,
    MAX(CASE WHEN rn_max = 1 THEN value_2 END) AS value_2
FROM cte
GROUP BY
    category;
  

снимок экрана из демонстрационной ссылки ниже

ДЕМОНСТРАЦИЯ

Редактировать:

Приведенный выше запрос должен использовать следующий индекс:

 CREATE INDEX idx ON yourTable (category, ID);
  

Это должно существенно ускорить операции с номерами строк.

Комментарии:

1. Это действительно дает met правильный ответ, но также выдает ошибку: Обратите внимание на . библиотеки классы Отображение Результаты.php#4241 — Неопределенный индекс: инструкция

2. @JMRC Тогда, возможно, у вашего PHP-скрипта какая-то проблема, или, возможно, вы не используете MySQL 8 . То, что я привел выше, я считаю лучшим ответом без использования объединений.

3. Возможно, это действительно был phpMyAdmin. Я попробую еще раз.

4. К сожалению, это было слишком медленно. Это заняло несколько минут, но 1, потому что это сработало в примере.

5. @JMRC Пожалуйста, попробуйте добавить соответствующий индекс, см. мой обновленный ответ.