Допустим, у вас есть такой запрос:
SELECT g, v
FROM t
GROUP BY g;
В этом случае для каждого возможного значения g
mysql выбирает одно из соответствующих значений v
.
Однако, какой из них выбран, зависит от некоторых обстоятельств.
Я где-то читал, что для каждой группы g сохраняется первое значение v
в том порядке, как записи были вставлены в таблицу t
.
Это довольно уродливо, потому что записи в таблице должны рассматриваться как набор , где порядок элементов не должен иметь значения. Это так "mysql-иш" ...
Если вы хотите определить, какое значение для v
оставить, вам нужно применить подвыбор для t
, например:
SELECT g, v
FROM (
SELECT *
FROM t
ORDER BY g, v DESC
) q
GROUP BY g;
Таким образом, вы определяете, в каком порядке записи подзапроса обрабатываются внешним запросом, поэтому вы можете доверять, какое значение v
будет выбрано для отдельных значений g
.
Однако, если вам нужны условия WHERE, будьте очень осторожны. Если вы добавите условие WHERE в подзапрос, то оно сохранит поведение, оно всегда вернет ожидаемое вами значение:
SELECT g, v
FROM (
SELECT *
FROM t
WHERE g = '737a8783-110c-447e-b4c2-1cbb7c6b72c9'
ORDER BY g, v DESC
) q
GROUP BY g;
Это то, что вы ожидаете, подвыбор фильтрует и упорядочивает таблицу. Он хранит записи, где g
имеет заданное значение, а внешний запрос возвращает это g
и первое значение для v
.
Однако, если вы добавите такое же условие WHERE к внешнему запросу, вы получите недетерминированный результат:
SELECT g, v
FROM (
SELECT *
FROM t
-- WHERE g = '737a8783-110c-447e-b4c2-1cbb7c6b72c9'
ORDER BY g, v DESC
) q
WHERE g = '737a8783-110c-447e-b4c2-1cbb7c6b72c9'
GROUP BY g;
Удивительно, но вы можете получить разные значения для v
при повторном выполнении одного и того же запроса, что ... странно. Ожидаемое поведение - получить все записи в соответствующем порядке из подзапроса, отфильтровав их во внешнем запросе, а затем выбрав их так же, как в предыдущем примере. Но это не так.
Он выбирает значение для v
, казалось бы, случайно. Тот же запрос вернул разные значения для v
, если я выполнял больше (~ 20) раз, но распределение было неравномерным.
Если вместо добавления внешнего WHERE вы указываете условие HAVING следующим образом:
SELECT g, v
FROM (
SELECT *
FROM t1
-- WHERE g = '737a8783-110c-447e-b4c2-1cbb7c6b72c9'
ORDER BY g, v DESC
) q
-- WHERE g = '737a8783-110c-447e-b4c2-1cbb7c6b72c9'
GROUP BY g
HAVING g = '737a8783-110c-447e-b4c2-1cbb7c6b72c9';
Тогда вы снова получаете последовательное поведение.
ЗАКЛЮЧЕНИЕ: Я бы предложил вообще не полагаться на эту технику. Если вы действительно хотите / должны избегать условий WHERE во внешнем запросе. Используйте его во внутреннем запросе, если можете, или в предложении HAVING во внешнем запросе.
Я проверил это с этими данными:
CREATE TABLE t1 (
v INT,
g VARCHAR(36)
);
INSERT INTO t1 VALUES (1, '737a8783-110c-447e-b4c2-1cbb7c6b72c9');
INSERT INTO t1 VALUES (2, '737a8783-110c-447e-b4c2-1cbb7c6b72c9');
в mysql 5.6.41.
Может быть, это просто ошибка, которая исправляется / исправляется в более новых версиях, пожалуйста, оставьте отзыв, если у вас есть опыт работы с более новыми версиями.