Получение правильных данных строки при использовании агрегатной функции MySQL MIN? [Дубликат]

0

Теперь, когда я понимаю, когда вы используете агрегированные функции, такие как AVG, SUM т.д., Вы должны иметь в виду, что любые другие поля, которые вы SELECT, которые также не участвуют в агрегатной функции, будут неопределенными, например:

SELECT AVG(amount), name, desc FROM some_table;

Я понимаю это, и это потому, что значение, исходящее из совокупной функции, не привязано ни к одной строке, и, следовательно, другие выбранные поля являются неопределенными.

Однако, если вы используете другой тип агрегированной функции, такой как MIN или MAX где то, что они получают, привязано к определенной строке, можно ли предположить, что любые другие выбранные поля, которые не входят в общую функцию, могут быть определены?... как результат будет привязан к определенной строке данных, в отличие от других результатов функции совокупности?

Например:

SELECT MIN(media_id),
       auction_id,
       media_url
FROM   auction_media
WHERE  auction_id IN( 119925, 124660, 124663, 129078,
                      129094, 134395, 149753, 152221,
                      154733, 154737, 154742, 157694,
                      161411, 165965, 165973 )
       AND media_type = 1
       AND upload_in_progress = 0
GROUP  BY auction_id;

Если я прав в своих мыслях, это всегда вернет правильный media_url прав?

  • 0
    Обычно вы группируете по выбранным столбцам.
Теги:
aggregate-functions
min

3 ответа

2
Лучший ответ

Однако, если вы используете другой тип агрегированной функции, такой как MIN или MAX, где то, что они получают, привязано к определенной строке, можно ли предположить, что любые другие выбранные поля, которые не входят в общую функцию, могут быть определены?

Нету. Например, несколько строк могут иметь минимальное или максимальное значение; для другого нет ничего, что останавливало бы запрос от выбора MIN (a), MAX (a), AVG (a) и SUM (a) сразу (и я очень сомневаюсь, что MySQL слишком усложнит его механизм запросов, чтобы воспользоваться "если запрос имеет только один агрегат...")


Примечание. Я вполне уверен, что единственная причина, по которой MySQL изначально даже разрешала такие запросы, заключалась в короткой руке в таких ситуациях, как:

SELECT a.*, SUM(b.X)
FROM a INNER JOIN b ON a.PK = b.a_PK
GROUP BY a.PK;

где автор запросов знает, что неагрегированные поля могут быть определены в силу группировки, а не агрегированного значения (значений).

  • 0
    Хм, вы делаете хорошую мысль. Однако для вашего первого замечания, в моем случае, для этой ситуации, media_id является уникальным и, следовательно, не может дублироваться.
  • 0
    Да, я чувствую, что основная часть моего ответа находится во втором пункте, и это заключенное в скобки примечание о маловероятных оптимизациях ... тем более, что MySQL является единственным rdbms, который даже разрешает такие агрегированные запросы, и даже в его последних выпусках по умолчанию используется конфигурация, которая запрещает их.
Показать ещё 3 комментария
2

MIN и MAX больше не привязаны ни к какой строке, кроме AVG или SUM. Все 4 из них являются результатом объединения нескольких строк, будь то все строки (например, вы первый запрос) или строки в группе (например, ваш второй запрос).

Если я прав в своих мыслях, это всегда вернет правильный медиа-прав?

Нет. Что делать, если ваши данные:

auction_id   media_id   media_url
119925       3          http://google.com
119925       5          http://yahoo.com
119925       3          http://bing.com

Ваш запрос SELECT MIN(media_id), auction_id, media_url GROUP BY auction_id вернет 3 для MIN(media_id) и 119925 для auction_id, но какой media_url он вернет?

media_url все еще неопределенна.

Понимаете, в данных нет ничего, что говорит о том, что media_url никак не связан с media_id.

Вы можете (думаете, вы) знать, что media_url всегда один и тот же для определенного media_id, но это не имеет значения для механизма SQL.

  • 0
    Я, вероятно, должен отметить, что media_id является уникальным.
  • 0
    @ Бретт Не имеет значения для движка SQL. media_url все еще не определен в отношении оператора SQL. Уникальные индексы никогда не будут влиять на результат запроса, хотя индексы, конечно, могут влиять на производительность получения этого результата. Уникальные индексы влияют на данные, которые можно вставить в таблицу, но не на запросы из таблицы.
2

Нет. Неагрегированные столбцы (которые не входят в group by) в запросе агрегирования поступают из произвольных и неопределенных строк. Это неудобное поведение объясняется тем, что синтаксис не разрешен в большинстве баз данных и почему по умолчанию самые последние версии MySQL "turn-it-off". Таким образом, ваш запрос вернет ошибку.

Вот один из способов сделать то, что вы хотите:

SELECT am.*
FROM auction_media am
WHERE auction_id IN (119925, 124660, 124663, 129078,
                      129094, 134395, 149753, 152221,
                      154733, 154737, 154742, 157694,
                      161411, 165965, 165973 ) AND
      media_type = 1 AND upload_in_progress = 0 AND
      media_id = (SELECT MIN(am2.media_id)
                  FROM auction_media m2
                  WHERE m2.auction_id = m.auction_id AND m2.media_type = m.media_type AND m2.upload_in_progress = m.upload_in_progress
                 );

Для производительности вам нужен индекс на auction_media(auction_id, media_type, upload_in_progress, media_id) и auction_media(media_type, upload_in_progress, auction_id).

  • 0
    Спасибо за это. У меня был похожий запрос раньше в основном запросе, но я пытался разделить часть о получении media_url в свой собственный запрос, чтобы избежать дорогостоящего соединения и подзапроса, поскольку он был действительно медленным.
  • 0
    Я думаю, что лучший способ сделать это сейчас - удалить все агрегатные функции и получить все media_urls, а затем просто обработать их через PHP, чтобы получить данные с самым низким media_id.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню