查看: 11720|回复: 18

[PL/SQL] 【大话IT】求助贴:关于从指定表中随机选取指定字段的某一条数据

[复制链接]
论坛徽章:
3
优秀写手
日期:2014-08-21 06:00:132015年新春福章
日期:2015-03-04 14:55:132015年新春福章
日期:2015-03-06 11:59:47
发表于 2014-11-12 21:04 | 显示全部楼层 |阅读模式
在工作过程中遇到一个需求,需要从一个表中随机取出一条满足条件的数据,插入到指定的表中。由于插入量极大(千万级),本人所写的方法执行速度过慢,特发帖求助,望各位大神指教一二。
举个例子:
--构建示例表
create table s(
id number not null,
name varchar(20),
age number);
--插入数据
insert into s values(1,'a',11);
insert into s values(2,'b',22);
insert into s values(3,'c',33);
insert into s values(4,'d',44);
insert into s values(5,'e',55);
insert into s values(6,'f',66);
insert into s values(7,'g',77);
insert into s values(8,'h',88);
insert into s values(9,'i',99);
insert into s values(10,'j',123);
commit;
现需求从s表中随机获取一个人的name插入函数中(其他相关函数省略了,现在只求一个高效方法把数据取出来)
即随机返回a或b或。。。中的一个
本人尝试了2种方式,但都存在一些问题,无法使用。也在此列出:
1.使用sample函数碰到这个问题,我首先想到的就是sample函数,具体代码如下:
select name from s sample(20) where rownum=1;
结果发现偶尔会出现取出来的是空值的情况,由于需要循环上千万次,这里就算是sample(99)也可能会因为出现空值而报错。无奈放弃。
2.使用随机函数(我现在使用的方法),具体代码如下:
select name from (select * from s order by dbms_random.value) where rownum= 1;
但执行后发现效率实在太低,无法满足大批量使用要求。


现跪求一解决方案,如一个高效的随机取值的方法。或者一个高效的判断函数,判断如返回的为空值则重新执行该语句


再次跪谢!





论坛徽章:
737
季节之章:春
日期:2015-07-31 17:16:29ITPUB季度 技术新星
日期:2014-07-17 14:37:00季节之章:秋
日期:2015-07-31 17:16:14季节之章:夏
日期:2015-07-31 17:16:29股神
日期:2014-10-15 09:23:31衰神
日期:2014-10-20 22:47:12季节之章:冬
日期:2015-07-31 17:16:14红钻
日期:2014-12-16 17:51:41洛杉矶湖人
日期:2016-09-23 08:18:15布鲁克林篮网
日期:2016-09-23 08:17:18
发表于 2014-11-12 22:03 | 显示全部楼层
不明觉厉。。。

使用道具 举报

回复
论坛徽章:
9
奥运会纪念徽章:羽毛球
日期:2012-10-08 11:33:492013年新春福章
日期:2013-02-25 14:51:242014年新春福章
日期:2014-02-18 16:47:53马上加薪
日期:2014-02-18 16:47:53马上加薪
日期:2015-01-13 21:26:15优秀写手
日期:2015-02-12 06:00:15慢羊羊
日期:2015-03-04 14:53:332015年新春福章
日期:2015-03-06 11:58:39
发表于 2014-11-12 22:47 | 显示全部楼层
能想到的也是第2种。。。关注。

使用道具 举报

回复
论坛徽章:
533
奥运会纪念徽章:垒球
日期:2008-09-15 01:28:12生肖徽章2007版:鸡
日期:2008-11-17 23:40:58生肖徽章2007版:马
日期:2008-11-18 05:09:48数据库板块每日发贴之星
日期:2008-11-29 01:01:02数据库板块每日发贴之星
日期:2008-12-05 01:01:03生肖徽章2007版:虎
日期:2008-12-10 07:47:462009新春纪念徽章
日期:2009-01-04 14:52:28数据库板块每日发贴之星
日期:2009-02-08 01:01:03生肖徽章2007版:蛇
日期:2009-03-09 22:18:532009日食纪念
日期:2009-07-22 09:30:00
发表于 2014-11-13 01:22 | 显示全部楼层
SAMPLE 写法带WHERE不就行了吗?

使用道具 举报

回复
论坛徽章:
3
优秀写手
日期:2014-08-21 06:00:132015年新春福章
日期:2015-03-04 14:55:132015年新春福章
日期:2015-03-06 11:59:47
 楼主| 发表于 2014-11-13 09:04 | 显示全部楼层
newkid 发表于 2014-11-13 01:22
SAMPLE 写法带WHERE不就行了吗?

请问你说的是哪种加where语句的方法呢?
我试过2种:
1.直接添加is not null,即:
select name from s sample(20) where rownum=1 and name is not null;
这种方法逻辑上都说不通,故而也会取出空值;


2.包装起来添加is not null,即:
select t.name from(
select name from s sample(20) where rownum=1) t
where t.name is not null;
这方法同样可能会取出空值呀。

使用道具 举报

回复
论坛徽章:
533
奥运会纪念徽章:垒球
日期:2008-09-15 01:28:12生肖徽章2007版:鸡
日期:2008-11-17 23:40:58生肖徽章2007版:马
日期:2008-11-18 05:09:48数据库板块每日发贴之星
日期:2008-11-29 01:01:02数据库板块每日发贴之星
日期:2008-12-05 01:01:03生肖徽章2007版:虎
日期:2008-12-10 07:47:462009新春纪念徽章
日期:2009-01-04 14:52:28数据库板块每日发贴之星
日期:2009-02-08 01:01:03生肖徽章2007版:蛇
日期:2009-03-09 22:18:532009日食纪念
日期:2009-07-22 09:30:00
发表于 2014-11-13 09:50 | 显示全部楼层
SELECT * FROM (select name from s sample(20) where  name is not null) WHERE rownum=1

使用道具 举报

回复
论坛徽章:
3
优秀写手
日期:2014-08-21 06:00:132015年新春福章
日期:2015-03-04 14:55:132015年新春福章
日期:2015-03-06 11:59:47
 楼主| 发表于 2014-11-13 09:53 | 显示全部楼层
本帖最后由 sunbocong 于 2014-11-13 09:55 编辑
newkid 发表于 2014-11-13 09:50
SELECT * FROM (select name from s sample(20) where  name is not null) WHERE rownum=1

也不行哦。。。还是可能会取到空值。

因为使用sample的话,是先进行where条件的判断,再从结果中按百分比取出数据的吧。

使用道具 举报

回复
招聘 : 系统分析师
论坛徽章:
483
马上有钱
日期:2014-02-19 11:55:14itpub13周年纪念徽章
日期:2014-09-29 01:14:14itpub13周年纪念徽章
日期:2014-10-08 15:15:25itpub13周年纪念徽章
日期:2014-10-08 15:15:25马上有对象
日期:2014-10-12 11:58:40马上有车
日期:2014-11-16 17:11:29慢羊羊
日期:2015-02-09 17:04:38沸羊羊
日期:2015-03-04 14:43:432015年新春福章
日期:2015-03-06 11:57:31ITPUB年度最佳版主
日期:2015-03-18 15:48:48
发表于 2014-11-13 10:53 | 显示全部楼层
sunbocong 发表于 2014-11-13 09:53
也不行哦。。。还是可能会取到空值。

因为使用sample的话,是先进行where条件的判断,再从结果中按百分 ...

我测试的结果是取不到空值的

使用道具 举报

回复
论坛徽章:
3
优秀写手
日期:2014-08-21 06:00:132015年新春福章
日期:2015-03-04 14:55:132015年新春福章
日期:2015-03-06 11:59:47
 楼主| 发表于 2014-11-13 11:04 | 显示全部楼层
lastwinner 发表于 2014-11-13 10:53
我测试的结果是取不到空值的

。。。我是这样测得:
declare
num varchar(1000);


begin
for i in 1..100 loop


select * into num from (select name from s sample(20) where name is not null) where rownum=1;


dbms_output.put_line(num);


end loop;


end;


执行后会报错ORA-01403:no data found
查看输出记录,发现只能执行到一半
ps:我是在pl/sql developer 中实验的,oracle 是11g   11.2.0.3

使用道具 举报

回复
论坛徽章:
3
优秀写手
日期:2014-08-21 06:00:132015年新春福章
日期:2015-03-04 14:55:132015年新春福章
日期:2015-03-06 11:59:47
 楼主| 发表于 2014-11-13 14:47 | 显示全部楼层
本帖最后由 sunbocong 于 2014-11-20 12:22 编辑

我想到了一种使用sample解决的方法,使用union all连接查询。代码如下:
select name from (
select name from s sample(20) union all select 'j' from dual
)
where rownum=1;

使用道具 举报

回复

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

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 
京ICP备09055130号-4  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表