Вопрос или проблема
Я пытаюсь рассчитать вес, используя обновление. В данном конкретном случае мне нужно применить группировку, так как нагрузка должна быть распределена по идентификатору клиента. Но группировка здесь работает некорректно. Обязательно использовать обновление.
Результаты
Ожидаемый результат: ожидаемый результат – это распределить по весу на основе идентификатора клиента и долей 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 | |
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 | |
1 | 10 | 33.33333333333333333333333333333333333333 | AAPL |
2 | 30 | 100 | ABB |
1 | 50 | 33.33333333333333333333333333333333333333 | TESLA |
Вы можете использовать функции 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 | |
1 | 10 | 0.1428571428571429 | AAPL |
2 | 30 | 1 | ABB |
1 | 50 | 0.7142857142857143 | TESLA |
Процентное соотношение весов распределяется так, что в сумме все веса для каждой группы (клиента) составляют 1.
Наблюдения
- При вычислении весов очень важно, чтобы результат был корректным в зависимости от значений для каждого клиентского ID. Использование коррелированного подзапроса – это ключевой элемент для достижения нужного результата.
- Возможно, потребуется округление значений, чтобы они соответствовали вашим требованиям к точности. Для этого вы можете использовать функции
ROUND
,FLOOR
,CEIL
илиTRUNC
.
Заключение
Работа с подзапросами в SQL может быть сложной, особенно при использовании конструкций UPDATE
и GROUP BY
. Однако, с помощью коррелированных подзапросов можно добиться нужных результатов, обеспечивая правильное распределение значений. Убедитесь, что вы тестируете свои запросы на пробных данных, чтобы удостовериться в правильности логики и отображения результатов.
Для дальнейших вопросов или прояснений, не стесняйтесь обращаться за дополнительной помощью!