a我考网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 280|回复: 3

[考试辅导] 怎样删除Oracle数据库中的冗余数据(二)

[复制链接]
发表于 2012-8-4 14:06:19 | 显示全部楼层 |阅读模式
 它将冗余数据选择到一个游标中,并根据(LastName,FirstName)来分组(在我们这个方案中),然后打开游标然后循环地取出每一行,然后用与先前的取出的键值进行比较,如果这是第一次取出这个值,或者这个值不是冗余键,那么跳过这个记录然后取下一个,不然的话,这就是这个组中的冗余记录,所以删掉它.   让我们运行一下这个存储过程
% v- _  w# O( S+ X  BEGIN6 M: S. Y  M" p, |+ L' C9 ]
  DeleteDuplicates;
: |; b+ J) s# T0 ~$ H  END;
* e- X- A, A' ]) d: ]* \  /
: P' A# X: a) w  SELECT LastName, FirstName, COUNT(*)( E4 {3 `8 B) J5 ]' }' m8 x
  FROM Customers
* z8 w  X* y# o0 a  GROUP BY LastName, FirstName% P- K4 [$ t, O
  HAVING COUNT(*) > 1;$ U+ X" V* W) v- ?9 u
  最后一个查询语句没有返回值,所以冗余数据没有了从表中取冗余数据的过程完全是由定义在csr_Duplicates 这个游标中的SQL语句来实现的,PL/SQl只是用来实现删除冗余数,那么能不能完全用SQL语句来实现呢?& @. w+ A( h$ ~9 l  p; G
  二.SQL解决方案,使用RANK()删除冗余数据Oracle8i分析函数RANK()来枚举每一个组中的元素,在我们的方案中, 我们应用这个方案,我们使用这个函数动态的把冗余数据连续的排列起来加上编号,组由Partintion by 这个语句来分开,然后用Order by 进行分组 SELECT ID, LastName, FirstName, RANK() OVER (PARTITION BY LastName,
  g* |$ K" d( D4 v  FirstName ORDER BY ID) SeqNumber
+ C4 P: U; ]( P. ^- k  FROM Customers
7 f1 |$ c, G  c9 w  ORDER BY LastName, FirstName;
- j! c& Y' D; U8 a: Q2 }  SQL2 j& e( ~# s% I1 v. j
  Listing 7. Output of single SQL statement that uses RANK()' v3 E; O% O: E( _* m, w
  显示的是根据记录的条数的个数来显示尤其对于冗余数据
* `$ N9 a' l" C! G/ J  ID LASTNAME FIRSTNAME SEQNUMBER8 d& L5 P& X! Q/ q" }

4 A. d" a3 y6 J) X! c  ----- --------------- ---------- ----------
回复

使用道具 举报

 楼主| 发表于 2012-8-4 14:06:20 | 显示全部楼层

怎样删除Oracle数据库中的冗余数据(二)

</p>  1018 Blake Becky 1
7 j) O- s) C  K! B& X( u8 D  1013 Blue Don 1
( U" d  x7 v; x% I/ E6 o" E  1000 Bradley Tom 1
$ R3 U& |) ?9 m' `0 C, {# l  1002 Chang Jim 1* o! u: h: R5 G8 \- V
  1008 Griffith David 1& {+ s1 o% ]' ?4 N+ K* ~1 {* }
  1020 Hill Larry 1
/ w" f/ M0 U* B# I$ c) f  1004 King Chuck 1
7 q- }) w: L$ v& [  1005 Krieger Jeff 1/ M  A$ g( {- j4 b- o
  1012 Krieger Jeff 2
  s7 U# `9 {+ n  l1 X) W+ o7 I  1017 Krieger Jeff 3
. e2 f9 {/ M3 L+ z" C* ~* M  1003 Loney Julie 1$ I# d  i0 m3 ?; J8 g5 C
  1007 Lord Don 1' P2 ]" s0 E7 U& t
  1015 Mason Paul 1
4 m4 R8 v; s3 {, L  1006 Monroe John 1( T7 h' ?6 a! g$ G3 J: n& J
  1009 Simon Michael 1
, D% K. n! I( V; v6 H  1010 Simon Michael 28 `/ d  T2 _7 k% U
  1001 Stone Tony 1, r8 _  G. A: _  i* Y/ Q( ^4 e7 \& j
  1011 Stone Tony 2% K0 j! [  i+ Z6 O
  1014 Stone Tony 3
! S& t- l' L8 ~" J+ [  1016 Stone Tony 4
, n3 a: a' ?! ^& O! G2 G  1019 Stone Tony 5
7 w+ `6 C" [  ~6 w/ o  我们可以看一到,SeqNumber这一列中的数值,冗余数据是根据ID号由小到大进行的排序,所有的冗余数据的SqlNumber都大于一,所有的非冗余数据都等于一,所以我们取自己所需,删除那么没用的SELECT ID, LastName, FirstName
5 q. M8 L! v* t( K+ p# k: W  FROM
( h  {/ b6 h6 o$ R# i  (SELECT ID, LastName, FirstName, RANK() OVER (PARTITION BY LastName,! w  X1 E. j" i; X: F6 _, Q
  FirstName ORDER BY ID) AS SeqNumber% O: @$ r  M7 r/ q/ C* P. t6 ]
  FROM Customers)
3 A2 T- ^) T$ \3 @& T' }; h. D  WHERE SeqNumber > 1;3 W7 x. S* i1 x; _/ W8 `+ V: u
  SQL% G! C( p: M/ {& g
  Listing 8. 冗余键的键值2 T/ ]* O7 ~! |- o
  有七行必须被删除
% l4 \( t/ K9 n* L2 I" [! H. k' w  ID LASTNAME FIRSTNAME
9 f( S+ g; x) w( R/ x+ p  ----- --------------- ----------, I  m2 H3 N( p6 o$ p( O8 j
  1012 Krieger Jeff& M- [9 D. F1 H: V5 I7 _
  1017 Krieger Jeff
' j# F# h. o) M" X. Z( h+ R  1010 Simon Michael
/ {! w$ m* d; }: ~) O% b) e  o  1011 Stone Tony
- y# _) V$ n. L# M" Z  W7 t  1014 Stone Tony% S$ j! {* B( D5 d) m
  1016 Stone Tony  V" E& `0 A0 k+ \  e" [
3 b5 R% r9 `/ }
  1019 Stone Tony
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-8-4 14:06:21 | 显示全部楼层

怎样删除Oracle数据库中的冗余数据(二)

</p>  7 rows selected.这显示有七行需要删除,还是用上一个表我测试了一下这个代码,它用了77秒种就删除了所有的数据准备好了用Sql语句来删除冗余数据,版本一它执行了135秒1 T* M# V$ B" U
  DELETE
( H5 L9 {$ I; n- i/ G; Y  FROM CUSTOMERS( j% y( t# b1 J+ G, g9 S
  WHERE ID IN9 k( h. k5 j: X% v
  (SELECT ID: i( i: Z  k5 V3 ?+ R
  FROM
2 h& J& Q3 c7 _4 U3 ~; K; V4 ^  (SELECT ID, LastName, FirstName, RANK() OVER (PARTITION BY LastName,
+ {6 Z/ [! u8 R( k) I  FirstName ORDER BY ID) AS SeqNumber& q& L7 `& M, f# B8 I" B
  FROM Customers)
$ J& M! i( A, y  ?* [  WHERE SeqNumber > 1);% U9 Y6 O* C9 v8 y& ^' X/ ]
  我们可以看到最后的两行语句对表中的数据进行了排序,这不是有效的,所以我们来优化一下最后一个查询语句,把Rank()函数应用到只含有冗余数据的组,而不是所有的列下面这个语句是比较有效率的,虽然它不像上一个查询那样精简SELECT ID, LastName, FirstName1 J8 h# P& ^4 }5 f0 v; N! g
  FROM9 x; U% E# Y- q' W7 w$ z9 ]- d1 T
  (SELECT ID, LastName, FirstName, RANK() OVER (PARTITION BY LastName,* J/ t0 X  m' U1 O+ e
  FirstName ORDER BY ID) AS SeqNumber
% K2 B/ @" K4 n: m# \  FROM: |/ A" W& P7 k: V
  (SELECT ID, LastName, FirstName% j5 T+ `& q" c+ u6 P$ G7 ~7 Y
  FROM Customers
0 ]) b3 L$ X. o" z8 X  WHERE (LastName, FirstName) IN (SELECT LastName, FirstName
- W$ }% |; i+ ~0 |2 r$ ?  FROM Customers2 F9 }  l0 y5 c  r; N
  GROUP BY LastName, FirstName9 E# k  A$ u+ m; e  _* H& d
  HAVING COUNT(*) > 1)))
1 z7 Q8 D+ o! t0 W  WHERE SeqNumber > 1;
- P% P4 Z: o; T6 ^4 u: o9 W  选择冗余数据只用了26秒钟,这样就提高了67%的性能,这样就提高了将这个作为子查询的删除查询的效率,8 @" o6 K4 T% a) v  U8 I( x& O# S
  DELETE; Z  m. L  x9 g9 O8 `$ K
  FROM Customers0 ~4 A2 l1 M! N( ]0 f7 Z7 f6 C8 O
  WHERE ID IN
  e! I+ y, R# b7 L2 L# G  (SELECT ID
" F! Z4 I: n3 Z+ T" E  FROM, ^( b0 `# x+ k8 a0 D# l
  (SELECT ID, LastName, FirstName, RANK() OVER (PARTITION BY LastName,
. h4 w" `8 V& W  ^; E4 h  FirstName ORDER BY ID) AS SeqNumber
% O7 l* U  @: m$ O2 d" X  FROM
) ~$ r/ O' y) C  N/ Q# P; P! Y  (SELECT ID, LastName, FirstName) }, t  _* P$ [$ Z& p
  FROM Customers3 \1 q3 J: _6 u+ [- ~' r
  WHERE (LastName, FirstName) IN (SELECT LastName, FirstName* P) ^2 M! _" {% }9 c2 M6 q
  FROM Customers
8 y: d+ B$ x6 n$ G; k$ y. z. P* H  GROUP BY LastName, FirstName
" J4 s( c0 n/ o& ^  HAVING COUNT(*) > 1)))6 n" \- J  l% p/ C  \6 H

, t) {. j7 M7 o1 |7 ?: N* O  WHERE SeqNumber > 1);
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-8-4 14:06:22 | 显示全部楼层

怎样删除Oracle数据库中的冗余数据(二)

</p>  现在只用了47秒钟的就完成的上面的任务,比起上一个136秒,这是一个很大的进步,相比之下,存储过程用了56秒,这样存储过程有些慢了使用PL/SQL语句我们和我们以上的代码,会得到更好的更精确的代码,和提高你代码的执行效率,虽然对于从数据库中枚举数据PL/SQL对于Sql两者没有什么差别,但是对于数据的比较上,PL/SQL就比SQL要快很多,但是如果冗余数据量比较小的话,我们尽量使用SQL而不使用PL/SQL如果你的数据表没有主键的话,那么你可以参考其它技术( E1 |4 _! s) B* r5 Y( K/ a% G
  Rank()其它的方法, G: r! s7 f" B2 |
  使用Rank()函数你可以对选择你所保留的数据,(或者是小ID的或者是大ID 的,就由RECDate这个列来决定这种情况下,你可以把REcdate加入到(Orderby )子句中,倒序或者正序
( A8 S4 w, @* z4 q" g9 P2 e7 y  这是一种保留最大Id的一种解决方案, a- \3 J1 X! p* s: B5 c
  DELETE% |6 {; L9 }! R: a, \/ O
  FROM Customers
. h6 x9 M$ S9 X5 @3 ~; z, d  WHERE ID IN
4 @; A# R( s* k, P0 v  (SELECT ID6 b  j7 @& [$ w
  FROM
# W; b3 U$ z7 R9 E1 y  (SELECT ID, LastName, FirstName, RANK() OVER (PARTITION BY LastName, FirstName ORDER BY RecDate DESC, ID) AS SeqNumber
6 v3 e0 \8 w- t, _, ?! Q) q  FROM
  h# |' `2 \! k- T0 m  (SELECT ID, LastName, FirstName, RecDate4 P8 q* P" V8 n, I! y
  FROM Customers
% O9 k/ [# p4 S* r7 Q2 y/ i  WHERE (LastName, FirstName) IN (SELECT LastName, FirstName* M" r) V# w# b; G
  FROM Customers) R# {  G2 P. ?/ R: T. ]9 {
  GROUP BY LastName, FirstName6 {% j% j! q/ B+ Y! O$ ?
  HAVING COUNT(*) > 1)))) w. F3 \: p9 d9 A( ?- k, f/ w2 w
  WHERE SeqNumber > 1);" s- |* b9 k  j, A
  这种技术保证了你可以控制每一个表中的保留的组,假设你有一个数据库,有一个促销或者有一个折扣信息,比如一个团体可以使用这种促销5次,或者个人可以使用这个折扣三次,为了指出要保留的组的个数,你可以在where 和having子句中进行设置,那么你将删除所有大于你. w& F' j8 X* p- ?8 A# b3 x
  设置有数的冗余组
8 U, D3 z6 S. p$ X# G  DELETE* b' Y, W0 X- a! x0 b5 e
  FROM Customers( K! p$ ]% E' O! G9 t1 U2 z5 d% u
  WHERE ID IN
% }) M9 t* M, N  \, }" p/ ?( {* ^  (SELECT ID$ E( p/ Y8 B$ Q
  FROM1 @" ?' U# I+ o6 D0 Y0 n& L
  (SELECT ID, LastName, FirstName, RANK() OVER (PARTITION BY LastName,
" `8 I7 }% a" }7 U  ^  FirstName ORDER BY ID) AS SeqNumber
. A: a0 u( y# @6 @) l  P  FROM, L, R6 Y7 j6 r0 g9 R  X! M
  (SELECT ID, LastName, FirstName; a: m8 H, N0 t* j* v
  FROM Customers0 Q3 S# E9 o. R
  WHERE (LastName, FirstName) IN (SELECT LastName, FirstName
6 X# Y" u1 |  L& ^& W; U7 _  FROM Customers
+ z8 m4 a9 P( ?/ Q$ H# _* ]% e  GROUP BY LastName, FirstName" c  F  ^6 p7 O% U1 ^$ n6 k
  HAVING COUNT(*) > 3)))
: g$ ^' g* t5 B% Q( k  WHERE SeqNumber > 3);
5 V/ r  d0 }/ j) w8 n  As you can see, using the RANK() function allows you to eliminate duplicates in a# t" Y, x0 W4 Z$ s$ E
  single SQL statement and gives you more capabilities by extending the power of
& V# }7 x2 J9 X. U- q3 `* q/ c  your
3 I, \- @$ T; g" a* n  queries.0 {1 m( _9 }3 h" x
  正如你所见使用Rank()可以消除冗余数据而且能给你很大的可伸展性
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Woexam.Com ( 湘ICP备18023104号 )

GMT+8, 2024-9-28 08:18 , Processed in 0.173091 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表