Как можно обновить столбец на основе значения другого столбца в SQL?
В основном у меня есть таблица продукта, как это:
date price
--------- -----
02-SEP-14 50
03-SEP-14 60
04-SEP-14 60
05-SEP-14 60
07-SEP-14 71
08-SEP-14 45
09-SEP-14 45
10-SEP-14 24
11-SEP-14 60
Мне нужно обновить таблицу в этой форме
date price id
--------- ----- --
02-SEP-14 50 1
03-SEP-14 60 2
04-SEP-14 60 2
05-SEP-14 60 2
07-SEP-14 71 3
08-SEP-14 45 4
09-SEP-14 45 4
10-SEP-14 24 5
11-SEP-14 60 6
Что я пробовал:
CREATE SEQUENCE user_id_seq
START WITH 1
INCREMENT BY 1
CACHE 20;
ALTER TABLE Product
ADD (ID number);
UPDATE Product SET ID = user_id_seq.nextval;
Это обновляет идентификатор обычным способом, как 1,2,3,4,5..
Я понятия не имею, как это сделать, используя основные команды SQL. Подскажите пожалуйста как мне это сделать. Заранее спасибо.
4 ответа
Вот один из способов создать представление из ваших базовых данных. Я предполагаю, что у вас есть более одного продукта (идентифицируемого по идентификатору продукта), и что даты цен не обязательно являются последовательными. Последовательность является отдельной для каждого идентификатора продукта. (Также, product
должно быть именем другой таблицы - где идентификатор продукта является первичным ключом, а у вас есть другая информация, такая как название продукта, категория и т. д. Таблица в вашем сообщении будет более правильно называться примерно так: price_history
.)
alter session set nls_date_format='dd-MON-rr';
create table product ( prod_id number, dt date, price number );
insert into product ( prod_id, dt, price )
select 101, '02-SEP-14', 50 from dual union all
select 101, '03-SEP-14', 60 from dual union all
select 101, '04-SEP-14', 60 from dual union all
select 101, '05-SEP-14', 60 from dual union all
select 101, '07-SEP-14', 71 from dual union all
select 101, '08-SEP-14', 45 from dual union all
select 101, '09-SEP-14', 45 from dual union all
select 101, '10-SEP-14', 24 from dual union all
select 101, '11-SEP-14', 60 from dual union all
select 102, '02-SEP-14', 45 from dual union all
select 102, '04-SEP-14', 45 from dual union all
select 102, '05-SEP-14', 60 from dual union all
select 102, '06-SEP-14', 50 from dual union all
select 102, '09-SEP-14', 60 from dual
;
commit;
create view product_vw ( prod_id, dt, price, seq ) as
select prod_id, dt, price,
count(flag) over (partition by prod_id order by dt)
from ( select prod_id, dt, price,
case when price = lag(price) over (partition by prod_id order by dt)
then null else 1 end as flag
from product
)
;
Теперь проверьте, как выглядит вид:
select * from product_vw;
PROD_ID DT PRICE SEQ
------- ------------------- ---------- ----------
101 02/09/0014 00:00:00 50 1
101 03/09/0014 00:00:00 60 2
101 04/09/0014 00:00:00 60 2
101 05/09/0014 00:00:00 60 2
101 07/09/0014 00:00:00 71 3
101 08/09/0014 00:00:00 45 4
101 09/09/0014 00:00:00 45 4
101 10/09/0014 00:00:00 24 5
101 11/09/0014 00:00:00 60 6
102 02/09/0014 00:00:00 45 1
102 04/09/0014 00:00:00 45 1
102 05/09/0014 00:00:00 60 2
102 06/09/0014 00:00:00 50 3
102 09/09/0014 00:00:00 60 4
WITH cts AS
(
SELECT row_number() over (partition by price order by price ) as id
,date
,price
FROM Product
)
UPDATE p
set p.id = cts.id
from product p join cts on cts.id = p.id
ПРИМЕЧАНИЕ: это отвечает на вопрос, который был первоначально задан. ОП изменил данные.
Если ваши данные не слишком велики, вы можете использовать коррелированный подзапрос:
update product p
set id = (select count(distinct p2.price)
from product p2
where p2.date <= p.date
);
Если ваши данные больше, то merge
более уместно.
Это лучший способ, которым вы пытаетесь сделать. Нет другого простого способа сделать это с помощью простых утверждений