Теперь, когда я понимаю, когда вы используете агрегированные функции, такие как 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
прав?
Однако, если вы используете другой тип агрегированной функции, такой как 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;
где автор запросов знает, что неагрегированные поля могут быть определены в силу группировки, а не агрегированного значения (значений).
media_id
является уникальным и, следовательно, не может дублироваться.
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.
media_id
является уникальным.
media_url
все еще не определен в отношении оператора SQL. Уникальные индексы никогда не будут влиять на результат запроса, хотя индексы, конечно, могут влиять на производительность получения этого результата. Уникальные индексы влияют на данные, которые можно вставить в таблицу, но не на запросы из таблицы.
Нет. Неагрегированные столбцы (которые не входят в 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)
.