如何删除数据库中的冗余数据…

二.SQL解决方案,使用RANK()删除冗余数据
Oracle8i分析函数RANK()来枚举每一个组中的元素,在我们的方案中, 我们应用这个方案,我们使用这个函数动态的把冗余数据连续的排列起来加上编号,组由Partintion by 这个语句来分开,然后用Order by 进行分组
SELECT ID, LastName, FirstName,
   RANK() OVER (PARTITION BY LastName,
      FirstName ORDER BY ID) SeqNumber
   FROM Customers
   ORDER BY LastName, FirstName;

SQL
Listin

7. Output of single SQL statement that uses RANK()
显示的是根据记录的条数的个数来显示尤其对于冗余数据
ID LASTNAME        FIRSTNAME   SEQNUMBER
----- --------------- ---------- ----------
 1018 Blake           Becky               1
 1013 Blue            Don                 1
 1000 Bradley         Tom                 1
 1002 Chang           Jim                 1
 1008 Griffith        David               1
 1020 Hill            Larry               1
 1004 King            Chuck               1
 1005 Krieger         Jeff                1
 1012 Krieger         Jeff                2
 1017 Krieger         Jeff                3
 1003 Loney           Julie               1
 1007 Lord            Don                 1
 1015 Mason           Paul                1
 1006 Monroe          John                1
 1009 Simon           Michael             1
 1010 Simon           Michael             2
 1001 Stone           Tony                1
 1011 Stone           Tony                2
 1014 Stone           Tony                3
 1016 Stone           Tony                4
 1019 Stone           Tony                5

我们可以看一到,SeqNumber这一列中的数值,冗余数据是根据ID号由小到大进行的排序,所有的冗余数据的SqlNumber都大于一,所有的非冗余数据都等于一,所以我们取自己所需,删除那么没用的
SELECT ID, LastName, FirstName
   FROM
   (SELECT ID, LastName, FirstName,
      RANK() OVER (PARTITION BY LastName,
         FirstName ORDER BY ID) AS SeqNumber
      FROM Customers)
   WHERE SeqNumber 1;


SQL
Listing 8. 冗余键的键值
有七行必须被删除
ID LASTNAME        FIRSTNAME
----- --------------- ----------
 1012 Krieger         Jeff
 1017 Krieger         Jeff
 1010 Simon           Michael
 1011 Stone           Tony
 1014 Stone           Tony
 1016 Stone           Tony
 1019 Stone  &n

bsp;        Tony

rows selected.

这显示有七行需要删除,还是用上一个表我测试了一下这个代码,它用了77秒种就删除了所有的数据准备好了用Sql语句来删除冗余数据,版本一它执行了135

DELETE
  FROM CUSTOMERS
  WHERE ID IN
   (SELECT ID
      FROM
      (SELECT ID, LastName, FirstName,
         RANK() OVER (PARTITION BY LastName,
            FirstName ORDER BY ID) AS SeqNumber
         FROM Customers)
      WHERE SeqNumber 1);
我们可以看到最后的两行语句对表中的数据进行了排序,这不是有效的,所以我们来优化一下最后一个查询语句,把Rank()函数应用到只含有冗余数据的组,而不是所有的列
下面这个语句是比较有效率的,虽然它不像上一个查询那样精简
SELECT ID, LastName, FirstName
   FROM
   (SELECT ID, LastName, FirstName,
      RANK() OVER (PARTITION BY LastName,
         FirstName ORDER BY ID) AS SeqNumber
      FROM
     (SELECT ID, LastName, FirstName
         FROM Customers
         WHERE (LastName, FirstName) IN
         (SELECT LastName, FirstName
            FROM Customers
            GROUP BY LastName, FirstName
            HAVING COUNT(*) 1)))
     WHERE SeqNumber 1;
选择冗余数据只用了26秒钟,这样就提高了67%的性能,这样就提高
了将这个作为子查询的删除查询的效率,
DELETE
  FROM Customers
  WHERE ID IN
  (SELECT ID
      FROM
      (SELECT ID, LastName, FirstName,
         RANK() OVER (PARTITION BY LastName,
            FirstName ORDER BY ID) AS SeqNumber
         FROM
        (SELECT ID, LastName, FirstName
            FROM Customers
            WHERE (LastName, FirstName) IN
            (SELECT LastName, FirstName
               FROM Customers
               GROUP BY LastName, FirstName
               HAVING COUNT(*) 1)))
        WHERE SeqNumber 1);
现在只用了47秒钟的就完成的上面的任务,比起上一个136秒,这是一个很大的进步,相比之下,存储过程用了56秒,这样存储过程有些慢了使用PL/SQL语句我们和我们以上的代码,会得到更好的更精确的代码,和提高你代码的执行效率,虽然对于从数据库中枚举数据PL/SQL对于Sql两者没有什么差别,但是对于数据的比较上,PL/SQL就比SQL要快很多,但是如果冗余数据量比较小的话,我们尽量使用SQL而不使用PL/SQL

如果你的数据表没有主键的话,那么你可以参考其它技术

Rank()其它的方法
使用Rank()函数你可以对选择你所保留的数据,(或者是小ID的或者是大ID 的,就由RECDate这个列来决定这种情况下,你可以把REcdate加入到(Order by )子句中,倒序或者正序


这是一种保留最大Id的一种解决方案

DELETE
  FROM Customers
  WHERE ID IN
  (SELECT ID
      FROM
      (SELECT ID, LastName, FirstName,
         RANK() OVER (PARTITION BY LastName,
            FirstName ORDER BY RecDate DESC, ID) AS SeqNumber
         FROM
        (SELECT ID, LastName, FirstName, RecDate
            FROM Customers
            WHERE (LastName, FirstName) IN
            (SELECT LastName, FirstName
               FROM Customers
               GROUP BY LastName, FirstName
               HAVING COUNT(*) 1)))
        WHERE SeqNumber 1);

这种技术保证了你可以控制每一个表中的保留的组,假设你有一个数据库,有一个促销或者有一个折扣信息,比如一个团体可以使用这种促销5次,或者个人可以使用这个折扣三次,为了指出要保留的组的个数,你可以在where having子句中进行设置,那么你将删除所有大于你设置有数的冗余组
DELETE
  FROM Customers
  WHERE ID IN
  (SELECT ID
      FROM
      (SELECT ID, LastName, FirstName,
         RANK

() OVER (PARTITION BY LastName,
            FirstName ORDER BY ID) AS SeqNumber
         FROM
        (SELECT ID, LastName, FirstName
            FROM Customers
            WHERE (LastName, FirstName) IN
            (SELECT LastName, FirstName
               FROM Customers
               GROUP BY LastName, FirstName
               HAVING COUNT(*) 3)))
        WHERE SeqNumber 3);
As you can see, using the RANK() function allows you to eliminate duplicates in a
single SQL statement and gives you more capabilities by extending the power of your
queries.
正如你所见使用Rank()可以消除冗余数据而且能给你很大的可伸展性 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值