如何删除数据库中的冗余数据(2)


它将冗余数据选择到一个游标中,并根据(LastName,FirstName)来分组(在我们这个方案中),然后打开游标然后循环地取出每一行,然后用与先前的取出的键值进行比较,如果这是第一次取出这个值,或者这个值不是冗余键,那么跳过这个记录然后取下一个,不然的话,这就是这个组中的冗余记录,所以删掉它.

    让我们运行一下这个存储过程

    BEGIN

    DeleteDuplicates;

    END;

    /

    SELECT LastName, FirstName, COUNT(*)

    FROM Customers

    GROUP BY LastName, FirstName

    HAVING COUNT(*) > 1;

    最后一个查询语句没有返回值,所以冗余数据没有了从表中取冗余数据的过程完全是由定义在csr_Duplicates 这个游标中的SQL语句来实现的,PL/SQl只是用来实现删除冗余数,那么能不能完全用SQL语句来实现呢?

    二.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

    Listing 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 Tony

    7 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加入到(Orderby )子句中,倒序或者正序

    这是一种保留最大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()可以消除冗余数据而且能给你很大的可伸展性



相关阅读:
虚拟化应用不断演进
css教程:DIV垂直居中的办法
浅析JavaScript中的静态类及JSON
搭建企业分支机构虚拟网络之Windows Server 2003
巧用UCenter Home管理相册 还原纯净绿色SNS
10个实用的PHP代码片段
使网页成黑白色调的滤镜
随机显示个性签名的js代码(兼容ie,firefox)
XHTML1.0与HTML兼容指引16条 小结
mysql中的“money”类型说明
流畅的运行Windows7减少不必要的程序和启动项
Windows7系统过期该怎么升级
javascript iframe内的函数调用实现方法
WPF的逻辑树和视觉树
快速导航
PHP MySQL HTML CSS JavaScript MSSQL AJAX .NET JSP Linux Mac ASP 服务器 SQL jQuery C# C++ java Android IOS oracle MongoDB SQLite wamp 交通频道 作文范文 快乐无处不在作文600字 是不是该报答妈妈了 冷空下的比赛 1. 2做一位小科学家 诚实--------人之根本 2016年进步青年入团申请书 班级管理工作计划范本 使东川。江楼月 天空之城作文100字 保洁员辞职信 今天好倒霉 有没有那么一刻,你是因为我 宝宝周岁生日致辞 小学五年级作文450字:军训 1 小学一年级作文400字:微笑着承受一切 常敏法师:我们念佛时也有光明吗? 2016“中国城市低碳行”报告 红尘残梦,谁来作陪? 鲸的自述作文600字 在农村青年中心建设工作推进会上的致辞 红军长征故事:再苦再难也坚信胜利 违愿 假如明天没有黎明100字作文 14护士转正工作总结范文 低年级语文教学总结 良好因素伴我行 一个人的旅程(四)作文700字 预备党员转正工作鉴定 风景,如此美丽作文800字 林忆月和一个外星人的奇历险(6)作文200字 小说《是对是错》之七十四章 离别当初依然是我 吻梦——爱你纯白的笑靥,让人迷恋。 发书之后的感受作文800字 保护绿色从我做起】 太阳落了,还有月亮 以科学发展观推进国税廉政文化建设 离婚的女人 冷落老婆的检讨书 党校科学发展观调研工作总结范文_科学发展观总结 发明,如此妙趣横生作文200字 诚实是生活之本 爱找茬的班主任 街道环保工作总结范文三篇 你我都犯罪。 工会干事辞职信 李响:坚持努力做好《职来职往》节目 【中学作文】我是谁 吃狼奶的羊600字 初中初二作文800字:蚂蚁虽小,力量甚大

Copyright © 2016 phpStudy |