Использование GROUP BY в запросе UPDATE

Вопрос или проблема

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

Результаты

введите описание изображения здесь

Ожидаемый результат: ожидаемый результат – это распределить по весу на основе идентификатора клиента и долей 0,14/0,14/1/0,71.

    CREATE TABLE VALUE_TBL 
     ( CLIEND_ID NUMBER(10),
       VALUE NUMBER,
       WEIGHT NUMBER,
       HOLDINGS VARCHAR(50)
     );

insert into value_tbl1(cliend_id,value,WEIGHT,HOLDINGS) values(1,10,33.33,'GOOGLE');
insert into value_tbl1(cliend_id,value,WEIGHT,HOLDINGS) values(1,10,33.33,'AAPL');
insert into value_tbl1(cliend_id,value,WEIGHT,HOLDINGS) values(2,30,100,'ABB');
insert into value_tbl1(cliend_id,value,WEIGHT,HOLDINGS) values(1,50,33.33,'TESLA');

Я пробовал следующее обновление, но безуспешно.

  update value_tbl y
  set weight = value / 
  (select sum(value) 
  from value_tbl x 
  group by x.cliend_id)

Ваш подзапрос вернет одну строку для каждого ID, а не только общую для ID, который вы обновляете. Как коррелированное обновление это будет выглядеть так:

update value_tbl y
  set weight = y.value / 
  (select sum(x.value) 
  from value_tbl x 
  where x.cliend_id = y.cliend_id)
CLIEND_ID VALUE WEIGHT HOLDINGS
1 10 .1428571428571428571428571428571428571429 GOOGLE
1 10 .1428571428571428571428571428571428571429 AAPL
2 30 1 ABB
1 50 .7142857142857142857142857142857142857143 TESLA

Что не является тем результатом, который вы показали. Чтобы получить эти проценты, вы бы использовали счет и делили на 100, а не value:

update value_tbl y
  set weight = 100 / 
  (select count(*) 
  from value_tbl x 
  where x.cliend_id = y.cliend_id)
CLIEND_ID VALUE WEIGHT HOLDINGS
1 10 33.33333333333333333333333333333333333333 GOOGLE
1 10 33.33333333333333333333333333333333333333 AAPL
2 30 100 ABB
1 50 33.33333333333333333333333333333333333333 TESLA

fiddle

Вы можете использовать функции round, floor/ceil или trunc, чтобы ограничить результаты до двух десятичных знаков или изменить определение вашего столбца, чтобы хранить только два десятичных знака.

Ответ или решение

Использование GROUP BY в запросе UPDATE в SQL

В SQL существует множество способов работать с данными, и одной из часто возникающих задач является необходимость обновления значений в таблице на основе агрегированных данных. В данном случае мы рассматриваем обновление весов, основываясь на конкретном клиенте и значениях. Давайте подробно рассмотрим запрос и то, как правильно использовать конструкцию GROUP BY в запросах типа UPDATE.

Проблема

Вы хотите распределить вес (weight) на основании значений (value) для каждого клиента (client_id). Изначально вы попробовали следующий запрос:

UPDATE value_tbl y
SET weight = value / 
(SELECT SUM(value) 
 FROM value_tbl x 
 GROUP BY x.cliend_id);

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

Решение

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

Вот как это должно выглядеть:

UPDATE value_tbl y
SET weight = y.value / 
(SELECT SUM(x.value) 
 FROM value_tbl x 
 WHERE x.cliend_id = y.cliend_id);

Этот запрос работает следующим образом:

  • UPDATE value_tbl y – мы обозначаем, что обновляем таблицу value_tbl с псевдонимом y.
  • SET weight = y.value / – здесь мы начинаем устанавливать новое значение для столбца weight.
  • (SELECT SUM(x.value) FROM value_tbl x WHERE x.cliend_id = y.cliend_id) – коррелированный подзапрос, который вычисляет сумму значений для клиентского ID текущей строки, что позволяет корректно обновить вес.

Результат

После выполнения этого запроса вы получите следующую таблицу:

CLIEND_ID VALUE WEIGHT HOLDINGS
1 10 0.1428571428571429 GOOGLE
1 10 0.1428571428571429 AAPL
2 30 1 ABB
1 50 0.7142857142857143 TESLA

Процентное соотношение весов распределяется так, что в сумме все веса для каждой группы (клиента) составляют 1.

Наблюдения

  • При вычислении весов очень важно, чтобы результат был корректным в зависимости от значений для каждого клиентского ID. Использование коррелированного подзапроса – это ключевой элемент для достижения нужного результата.
  • Возможно, потребуется округление значений, чтобы они соответствовали вашим требованиям к точности. Для этого вы можете использовать функции ROUND, FLOOR, CEIL или TRUNC.

Заключение

Работа с подзапросами в SQL может быть сложной, особенно при использовании конструкций UPDATE и GROUP BY. Однако, с помощью коррелированных подзапросов можно добиться нужных результатов, обеспечивая правильное распределение значений. Убедитесь, что вы тестируете свои запросы на пробных данных, чтобы удостовериться в правильности логики и отображения результатов.

Для дальнейших вопросов или прояснений, не стесняйтесь обращаться за дополнительной помощью!

Оцените материал
Добавить комментарий

Капча загружается...