2009-07-17 1 views
2

При использовании Group By, как вы держите другие поля в синхронизации при использовании агрегатов
Группировка проблемы

Здесь я пытаюсь найти мин значение COL4 при col2 = ххх

select col1, col2, col3, min(col4) 
from table 
where col2 = 'xxx' 
group by col3 

Я могу получить минимальное значение в col4, но col1 неверен, но col2, col3, col4.

Может ли кто-нибудь показать мне, как это сделать?

Благодаря

+2

Это действительный запрос в MySQL? У меня нет MySQL, но SQL Server отказывается от этого, поскольку вы ссылаетесь на столбцы в 'select', но не в вашей' group by'. Во всяком случае, можете ли вы разместить образцы данных, чтобы мы знали, что такое «правильный»? – Eric

+0

@ Эрик: это расширение 'MySQL', которое позволяет вам выбрать негрупповое значение из одной строки для каждой группы в определенном порядке. – Quassnoi

+0

@Ben: Не могли бы вы предоставить некоторые примеры данных и результаты, которые вы хотели бы получить? – Quassnoi

ответ

3

Вы используете нестандартную MySQLextension к GROUP BY.

Этот запрос на самом деле читается как «для каждого отдельного значения col3, выберите минимальное значение col4 наряду со значениями col1 и col2 из одного ряда table, имеющего это значение col3 в произвольном порядке»

Мол, если мы имеем следующие данные:

col1 col2 col3 col4 
---- --- --- ---- 

A A 1 1 
B B 1 2 
C C 2 3 
D D 2 4 

, этот запрос:

SELECT col1, col2, col3, MIN(col4) 
FROM mytable 
GROUP BY 
     col3 

возвратит одно из следующих действий:

col1 col2 col3 col4 
---- --- --- ---- 
A A 1 1 
C C 2 3 

col1 col2 col3 col4 
---- --- --- ---- 
B B 1 1 
C C 2 3 

col1 col2 col3 col4 
---- --- --- ---- 
A A 1 1 
D D 2 3 

col1 col2 col3 col4 
---- --- --- ---- 
B B 1 1 
D D 2 3 

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

Это эквивалент аналитической функции FIRST_VALUE, но ни в каком конкретном порядке.

Update:

Для выбора значения col1 и col2, соответствующие минимальному значению col4 внутри каждой группы, используйте:

SELECT col1, co2, col3, col4 
FROM (
     SELECT col1, col2, col3, col4, 
       COALESCE(@col3 = col3, FALSE) AS grp, 
       @col3 := col3 AS nv 
     FROM (
       SELECT @col3 := NULL 
       ) vars, table 
     WHERE col2 = 'xxx' 
     ORDER BY 
       col3, col4 
     ) q 
WHERE NOT grp 
+3

Сладкая мать всего святого, что небольшое расширение должно распространяться на трупы надежд и мечтаний. Какая опасная реализация, особенно учитывая, что таблицы не хранятся в каком-либо конкретном порядке. Единственное, что было бы надежным, было бы, если бы ваша колонка имела одно и только одно потенциальное значение для всех случаев. Даже тогда я не уверен, сколько вы выиграете. – Eric

+0

@ Эрик: когда я * знаю *, что все значения, которые у меня есть, будут одинаковыми для любой группы (например, когда я группирую «ПЕРВИЧНЫЙ КЛЮЧ» объединенной таблицы и хочу выбирать неключевые значения), необходимость в 'GROUP BY' иногда раздражает меня. Это очень хорошая функция при правильном использовании. – Quassnoi

+0

@ Эрик: Да, когда вы группируетесь по идентификатору, и у вас есть много столбцов для выбора, перечисление их всех в группе избыточно. Теперь, если бы это ограничило бы случаи, когда вы группируете уникальный/pk, это было бы неплохо. – Draemon

0
select a.col3, a.col2, a.col1, a.col4 
from table as a natural join 
     (select col3, min(col4) as col4 from table 
     where col2='xxx' 
     group by col3) as b 
where a.col2 = 'xxx' -- sometimes this helps the optimizer even though it's redundant 

вы можете получить в немного проблема здесь, когда может быть несколько строк с одинаковыми col3, col4 и col2, но разные col1 - довольно простые, чтобы исправить с помощью rownums и т. д., но это получает db-spec IFIC.

0

Я думаю, вы хотите, чтобы col1-3 соответствовал min (col4) для каждого col3?

Что-то вроде:

select X.col1, X.col2, X.col3, X.col4 from table X 
join (select col3, min(col4) as mcol4 from table where col2='xxx' group by col3) as Y 
on X.col3=Y.col3 and X.col4=Y.mcol4 
where X.col2='xxx'; 
+0

@Draemon: 'col2 = 'xxx'' также должен быть во внутреннем подзапросе. Также обратите внимание, что это решение не является дублирующим, и здесь мы не можем использовать первичный ключ. – Quassnoi

+0

Да, вы правы (отредактированы). Время, в которое я делал эти дубликаты, не имело значения - я только что выбрал первую строку. Но ты совершенно прав. – Draemon