В group by, есть ли способ сказать SQL, что агрегатная функция не требуется для определенного столбца? - PullRequest
1 голос
/ 06 ноября 2019

Я недавно начал работать с T-SQL и столкнулся с трудностями в работе группы по функциональности.

Допустим, у меня есть таблица с 3 столбцами: Column_1, Column_2 и Column_3. Я знаю, что для данного значения Column_1, Column_2 всегда будет иметь данное значение. Столбец_3, с другой стороны, не зависит от Столбца_1.

Таким образом, таблица может выглядеть следующим образом:

Column_1    Column_2    Column_3 
1           42          57 
1           42          35 
2           3           5
2           3           6 
5           78          45 

Я хочу создать группу для Column_1, чтобы агрегировать Column_3 (скажем, с помощью sum ()). Однако, поскольку я делаю группу, я должен группировать или объединять Column_2, хотя я знаю, что в этом нет необходимости.

Таким образом, мой запрос SQL будет:

select Column_1, Column_2, sum(Column_3) 
from Table 
group by Column_1, Column_2

или

select Column_1, max(Column_2), sum(Column_3) 
from Table 
group by Column_1
(using max as a workaround to avoid grouping by Column_2)

Мой вопрос таков: есть ли способ сообщить SQL, что агрегатная функция не требуетсядля столбца_2 и SQL проверить, что предположение правильно?

Я бы посчитал этот вариант оптимальным, поскольку он позволяет мне быть уверенным, что мое предположение верно. При использовании двух предыдущих запросов я никогда не уверен на 100% в этом (кроме случаев, когда я проверяю это другим способом перед запросом), и может быть трудно идентифицировать ошибку (особенно при использовании максимального обходного пути).

В идеале я хотел бы иметь возможность написать что-то вроде:

select Column_1, no_agg_necessary(Column_2), sum(Column_3) 
from Table 
group by Column_1

, которое выдает предупреждение, если значения Column_2 не идентичны при группировании по заданному значению Column_1.

Я думал, что что-то вроде этого, чтобы выбрать Column_2, могло бы удовлетворить мою потребность:

case when count(distinct Column_2) = 1 then max(Column_2) else raiseerror() end as Column_2

Но не представляется возможным использовать Raiser-() в таком контексте и добавить различныезамедляет запрос.

Вам известны какие-либо функции SQL, которые бы отвечали моим потребностям?

Ответы [ 2 ]

0 голосов
/ 06 ноября 2019

В данных вашего примера отсутствует "проблема"

Как бы вы обработали запрос, если бы я добавил строку

1 - 41 - 19

Теперь у вас есть несколькозначения для этого столбца. Как бы хотелось получить результат?

41? 42? «Неправильно»?

Таким образом, чтобы сохранить правильность данных, вам нужно было бы нарезать их на 2 записи результатов, скорее всего, чего бы вы достигли, добавив их в предложение group.

ЕслиВы не заботитесь о данных, так как вы можете использовать фиктивную функцию, такую ​​как min () или max (), или, если вам захочется, вы можете ввести значение «invalid», если Min () <> Max ()

0 голосов
/ 06 ноября 2019

То, что вы запрашиваете, не поддерживается в SQL Server или любой другой базе данных. Функциональные зависимости поддерживаются в некоторых базах данных, но они смотрят на определение таблиц, чтобы увидеть, должно ли значение быть связано (то есть column1 равно unique). Они не проверяют, имеют ли данные уникальное значение в других обстоятельствах.

SQL в целом - и SQL Server в частности - не особенно хорош в генерировании ошибок в операторах SELECT. Это возможно с помощью CASE выражений. В неагрегированном запросе SQL Server гарантирует порядок оценки, вплоть до того, что он не оценивает ошибки на этапе компиляции.

Таким образом, вы могли бы написать то, что вы хотите:

select x,
       (case when min(y) = max(y)
             then min(y) else convert(int, 'Bad column value')
        end)
from (values (1, 1), (1, 1), (1, 2)) v(x, y)
group by x;

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

...