Ati*_*nch 1 sql oracle join aggregate-functions sql-update
我正在尝试修复一个大型股票交易所数据库的错误.一列(数量)在每个刻度上具有交易量,而其他列存储累积量(即,当天的先前刻度的总和).在某些情况下,这第二列是错误的(不是很多,所以我们可以安全地假设相邻的刻度线没有错误).因此理论上修复很容易:只需搜索累积量减少的刻度(这就足够了),然后从最后一个刻度中选择累积量并将当前刻度的数量相加.问题是我一直在努力开始在oracle中执行此操作的查询,但由于我缺乏sql的专业知识,我正在努力.这是我到目前为止所获得的:
update
(
select m.cumulative_volume, q.cum_volume_ant, q.quantity from
market_data_intraday_trades m
join
(
select * from
(select
product_key,
sequence_number,
lead(product_key) over (order by product_key, sequence_number) as product_key_ant,
to_char(trade_date_time, 'yyyymmdd') as fecha,
to_char(lag(trade_date_time) over (order by product_key, sequence_number), 'yyyymmdd') as fecha_ant,
cumulative_volume,
lead(cumulative_volume) over (order by product_key, sequence_number) as cum_volume_ant,
cumulative_volume - lead(cumulative_volume) over (order by product_key, sequence_number) as dif
from market_data_intraday_trades)
where product_key = product_key_ant
and fecha = fecha_ant
and dif < 0
and rownum < 10
) q
on m.sequence_number = q.sequence_number
)
set m.cumulative_volume = q.cum_volume_ant + q.quantity
Run Code Online (Sandbox Code Playgroud)
目前的问题是我似乎无法在外部计算中使用内部查询中的数量.
也许使用时态表或pl/sql或游标,所有这些都会更清晰和/或更容易,但由于公司策略,我没有权利这样做,只需选择和更新.
如果你能指点我解决这个问题,我将非常感激.
提前致谢!
PS.Fecha是西班牙语的约会,以防万一:)
这是一些测试数据.如您所见,第四行的CUMULATIVE_VOLUME错误.
SQL> select product_key
2 , trade_date_time
3 , quantity
4 , cumulative_volume
5 , sum (quantity) over (partition by product_key order by sequence_number) as running_total
6 from market_data_intraday_trades
7 order by sequence_number
8 /
PROD TRADE_DAT QUANTITY CUMULATIVE_VOLUME RUNNING_TOTAL
---- --------- ---------- ----------------- -------------
ORCL 23-JUN-10 100 100 100
ORCL 23-JUN-10 50 150 150
ORCL 25-JUN-10 100 250 250
ORCL 26-JUN-10 100 250 350
ORCL 26-JUN-10 50 400 400
ORCL 27-JUN-10 75 475 475
6 rows selected.
SQL>
Run Code Online (Sandbox Code Playgroud)
最简单的解决方案是使用计算的运行总计更新所有行:
SQL> update market_data_intraday_trades m
2 set m.cumulative_volume =
3 ( select inq.running_total
4 from (
5 select sum (quantity) over (partition by product_key
6 order by sequence_number) as running_total
7 , cumulative_volume
8 , rowid as row_id
9 from market_data_intraday_trades
10 ) inq
11 where m.rowid = inq.row_id
12 )
13 /
6 rows updated.
SQL> select product_key
2 , trade_date_time
3 , quantity
4 , cumulative_volume
5 , sum (quantity) over (partition by product_key
6 order by sequence_number) as running_total
7 , rowid as row_id
8 from market_data_intraday_trades
9 order by sequence_number
10 /
PROD TRADE_DAT QUANTITY CUMULATIVE_VOLUME RUNNING_TOTAL
---- --------- ---------- ----------------- -------------
ORCL 23-JUN-10 100 100 100
ORCL 23-JUN-10 50 150 150
ORCL 25-JUN-10 100 250 250
ORCL 26-JUN-10 100 350 350
ORCL 26-JUN-10 50 400 400
ORCL 27-JUN-10 75 475 475
6 rows selected.
SQL>
Run Code Online (Sandbox Code Playgroud)
但是,如果您有大量数据并且您真的不希望所有这些不必要的更新,那么再次使用相同的查询来限制命中:
SQL> update market_data_intraday_trades m
2 set m.cumulative_volume =
3 ( select inq.running_total
4 from (
5 select sum (quantity) over (partition by product_key
6 order by sequence_number) as running_total
7 , cumulative_volume
8 , rowid as row_id
9 from market_data_intraday_trades
10 ) inq
11 where m.rowid = inq.row_id
12 )
13 where m.rowid in
14 ( select inq.row_id
15 from (
16 select sum (quantity) over (partition by product_key
17 order by sequence_number) as running_total
18 , cumulative_volume
19 , rowid as row_id
20 from market_data_intraday_trades
21 ) inq
22 where m.cumulative_volume != running_total
23 )
24
SQL> /
1 row updated.
SQL> select product_key
2 , trade_date_time
3 , quantity
4 , cumulative_volume
5 , sum (quantity) over (partition by product_key
6 order by sequence_number) as running_total
7 from market_data_intraday_trades
8 order by sequence_number
9 /
PROD TRADE_DAT QUANTITY CUMULATIVE_VOLUME RUNNING_TOTAL
---- --------- ---------- ----------------- -------------
ORCL 23-JUN-10 100 100 100
ORCL 23-JUN-10 50 150 150
ORCL 25-JUN-10 100 250 250
ORCL 26-JUN-10 100 350 350
ORCL 26-JUN-10 50 400 400
ORCL 27-JUN-10 75 475 475
6 rows selected.
SQL>
Run Code Online (Sandbox Code Playgroud)
我尝试了尼古拉斯使用MERGE的建议.如果您使用10g或更高,那么这将有效.您需要最新版本的Oracle,因为9i不支持带UPDATE的MERGE但没有INSERT(而8i根本不支持MERGE).
SQL> merge into market_data_intraday_trades m
2 using ( select running_total
3 , row_id
4 from
5 ( select sum (quantity) over (partition by product_key
6 order by sequence_number) as running_total
7 , cumulative_volume
8 , rowid as row_id
9 from market_data_intraday_trades
10 )
11 where cumulative_volume != running_total
12 ) inq
13 on ( m.rowid = inq.row_id )
14 when matched then
15 update set m.cumulative_volume = inq.running_total
16 /
1 row merged.
SQL>
Run Code Online (Sandbox Code Playgroud)
这个解决方案比其他解决方案更整洁.
| 归档时间: |
|
| 查看次数: |
3952 次 |
| 最近记录: |