楼主: metaking

[SQL] 请教newkid:避免使用union 或圈套循环的查询sql

[复制链接]
论坛徽章:
57
SQL极客
日期:2013-12-09 14:13:35秀才
日期:2016-01-21 13:42:39秀才
日期:2016-01-13 12:14:26SQL大赛参与纪念
日期:2016-01-13 10:32:19SQL数据库编程大师
日期:2016-01-13 10:30:43秀才
日期:2015-12-14 14:47:54秀才
日期:2015-10-19 15:50:392015年新春福章
日期:2015-03-06 11:58:18懒羊羊
日期:2015-03-04 14:52:11优秀写手
日期:2014-11-08 06:00:14
11#
发表于 2012-3-15 12:17 | 只看该作者
select * from (
  select * from t_bank_code
  where '123456789' like range||'%'
  order by rules desc
  )
  where rownum=1

使用道具 举报

回复
论坛徽章:
2
ITPUB十周年纪念徽章
日期:2011-11-01 16:20:28优秀写手
日期:2014-01-25 06:00:12
12#
 楼主| 发表于 2012-3-15 13:18 | 只看该作者
xgghxkhuang 发表于 2012-3-15 12:17
select * from (
  select * from t_bank_code
  where '123456789' like range||'%'

这个结果没有问题,数据多时效率不高

使用道具 举报

回复
论坛徽章:
57
SQL极客
日期:2013-12-09 14:13:35秀才
日期:2016-01-21 13:42:39秀才
日期:2016-01-13 12:14:26SQL大赛参与纪念
日期:2016-01-13 10:32:19SQL数据库编程大师
日期:2016-01-13 10:30:43秀才
日期:2015-12-14 14:47:54秀才
日期:2015-10-19 15:50:392015年新春福章
日期:2015-03-06 11:58:18懒羊羊
日期:2015-03-04 14:52:11优秀写手
日期:2014-11-08 06:00:14
13#
发表于 2012-3-15 15:15 | 只看该作者
我的思路是这样的
1.因为range是字符,所以会按照字符排序
如果查询满足条件,一定满足
卡号  between     range     and  to_char(range+1)
2.我想通过上面的恒等式建立索引或函数索引,但是实践下来发现range+1>=卡号的条件索引能用上,但是卡号<=range的条件始终无法用上,
建议你提出思路,然后提交你们的开发dba,他们应该有手段。

使用道具 举报

回复
论坛徽章:
57
SQL极客
日期:2013-12-09 14:13:35秀才
日期:2016-01-21 13:42:39秀才
日期:2016-01-13 12:14:26SQL大赛参与纪念
日期:2016-01-13 10:32:19SQL数据库编程大师
日期:2016-01-13 10:30:43秀才
日期:2015-12-14 14:47:54秀才
日期:2015-10-19 15:50:392015年新春福章
日期:2015-03-06 11:58:18懒羊羊
日期:2015-03-04 14:52:11优秀写手
日期:2014-11-08 06:00:14
14#
发表于 2012-3-15 16:42 | 只看该作者
create table  rptdata.t_bank_code
     (bank_id varchar2(10),--bank_id
      rules number(10), --range μ?3¤?è
      range varchar2(15) --bank bin
      );
insert into rptdata.t_bank_code
select
dbms_random.string('A',9),
null,
'3'||to_char(trunc(dbms_random.value(0,99999999)))
from dual
connect by level<=1000000;
update rptdata.t_bank_code
set rules =length(range) ;
commit;
create index rptdata.vv_idx1 on rptdata.t_bank_code(to_char(to_number(range)+1),range DESC );
CREATE TABLE RPTDATA.SAMP
AS
SELECT AA FROM (
SELECT RANGE||LPAD(DBMS_RANDOM.value(0,TO_NUMBER(LPAD('9',(15-LENGTH(RANGE)),'9'))),15-LENGTH(RANGE),'0') AA
FROM  rptdata.t_bank_code vvv
ORDER BY DBMS_RANDOM.value)
WHERE ROWNUM<=10000
SELECT LPAD('m',10,'0') FROM DUAL;
--TEST
CREATE OR REPLACE PACKAGE TEST_TURN
IS
PROCEDURE P_IDX;
PROCEDURE P_FUL;
END;
/
CREATE OR REPLACE PACKAGE BODY TEST_TURN AS
procedure P_IDX IS
T_IDX RPTDATA.t_bank_code%ROWTYPE;
BEGIN
FOR AA IN (SELECT aa  CARD FROM  RPTDATA.SAMP WHERE ROWNUM<=100)
LOOP
SELECT *  INTO T_IDX FROM (
SELECT * FROM (
SELECT  /*+ index(vvv vv_idx1) */  *
FROM  rptdata.t_bank_code vvv
WHERE
to_char(to_number(range)+1) >=AA.CARD AND
RANGE  <=AA.CARD  )
WHERE substr(AA.CARD,1,rules)=range
ORDER BY RULES DESC )
WHERE ROWNUM=1;
END LOOP;
END P_IDX;
PROCEDURE P_FUL
AS
T_FUL RPTDATA.t_bank_code%ROWTYPE;
BEGIN
FOR AA IN (SELECT aa  CARD FROM  RPTDATA.SAMP WHERE ROWNUM<=100)
LOOP
SELECT * INTO T_FUL FROM (
SELECT * FROM  rptdata.t_bank_code vvv
WHERE substr(AA.CARD,1,rules)=range
ORDER BY RULES DESC )
WHERE ROWNUM=1;
END LOOP;
END P_FUL;
END TEST_TURN;
/
SET TIMING ON;
SET SERVEROUTPUT ON;
EXEC TEST_TURN.P_FUL;--100次75秒
EXEC TEST_TURN.P_IDX;--100次24秒
--结果完全符合要求
--方案:
create index rptdata.vv_idx1 on rptdata.t_bank_code(to_char(to_number(range)+1),range DESC );
--查询
SELECT *   FROM (
SELECT * FROM (
SELECT  /*+ index(vvv vv_idx1) */  *
FROM  rptdata.t_bank_code vvv
WHERE
to_char(to_number(range)+1) >=AA.CARD AND
RANGE  <=AA.CARD  )
WHERE substr(AA.CARD,1,rules)=range
ORDER BY RULES DESC )
WHERE ROWNUM=1;



     

使用道具 举报

回复
论坛徽章:
520
奥运会纪念徽章:垒球
日期: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
15#
发表于 2012-3-15 21:28 | 只看该作者
SELECT * FROM (SELECT * FROM t_bank_code WHERE SUBSTR('305550123456789',1,rules)=range ORDER BY range DESC) WHERE ROWNUM=1;

使用道具 举报

回复
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
16#
发表于 2012-3-15 23:10 | 只看该作者
与此相关的算法是字符串匹配,有个相关术语叫“模”,楼主可以查查相关的资料

使用道具 举报

回复
论坛徽章:
57
SQL极客
日期:2013-12-09 14:13:35秀才
日期:2016-01-21 13:42:39秀才
日期:2016-01-13 12:14:26SQL大赛参与纪念
日期:2016-01-13 10:32:19SQL数据库编程大师
日期:2016-01-13 10:30:43秀才
日期:2015-12-14 14:47:54秀才
日期:2015-10-19 15:50:392015年新春福章
日期:2015-03-06 11:58:18懒羊羊
日期:2015-03-04 14:52:11优秀写手
日期:2014-11-08 06:00:14
17#
发表于 2012-3-16 09:24 | 只看该作者
--方案:
create index rptdata.vv_idx1 on rptdata.t_bank_code(to_char(to_number(range)+1),range DESC );
--查询
SELECT *   FROM (
SELECT * FROM (
SELECT  /*+ index(vvv vv_idx1) */  *
FROM  rptdata.t_bank_code vvv
WHERE
to_char(to_number(range)+1) >=:CARD AND
RANGE  <=:CARD  )
WHERE substr(:CARD,1,rules)=range
ORDER BY RULES DESC )
WHERE ROWNUM=1;
楼主可以试验一下上面的方案,
to:newkid 你的方法数据肯定对的,但是楼主说数据量较大,你的这个消耗太多了,见前面的帖子。

使用道具 举报

回复
论坛徽章:
2
ITPUB十周年纪念徽章
日期:2011-11-01 16:20:28优秀写手
日期:2014-01-25 06:00:12
18#
 楼主| 发表于 2012-3-16 09:46 | 只看该作者
xgghxkhuang 发表于 2012-3-16 09:24
--方案:
create index rptdata.vv_idx1 on rptdata.t_bank_code(to_char(to_number(range)+1),range DESC  ...

谢谢xgghxkhuang:
这个方法逻辑读减少很多,关键是索引建的比较好,基本一次定位到记录

使用道具 举报

回复
论坛徽章:
57
SQL极客
日期:2013-12-09 14:13:35秀才
日期:2016-01-21 13:42:39秀才
日期:2016-01-13 12:14:26SQL大赛参与纪念
日期:2016-01-13 10:32:19SQL数据库编程大师
日期:2016-01-13 10:30:43秀才
日期:2015-12-14 14:47:54秀才
日期:2015-10-19 15:50:392015年新春福章
日期:2015-03-06 11:58:18懒羊羊
日期:2015-03-04 14:52:11优秀写手
日期:2014-11-08 06:00:14
19#
发表于 2012-3-16 12:25 | 只看该作者
metaking 发表于 2012-3-16 09:46
谢谢xgghxkhuang:
这个方法逻辑读减少很多,关键是索引建的比较好,基本一次定位到记录

互相学习,欢迎常来。

使用道具 举报

回复
论坛徽章:
57
SQL极客
日期:2013-12-09 14:13:35秀才
日期:2016-01-21 13:42:39秀才
日期:2016-01-13 12:14:26SQL大赛参与纪念
日期:2016-01-13 10:32:19SQL数据库编程大师
日期:2016-01-13 10:30:43秀才
日期:2015-12-14 14:47:54秀才
日期:2015-10-19 15:50:392015年新春福章
日期:2015-03-06 11:58:18懒羊羊
日期:2015-03-04 14:52:11优秀写手
日期:2014-11-08 06:00:14
20#
发表于 2012-3-16 13:48 | 只看该作者
xgghxkhuang 发表于 2012-3-16 12:25
互相学习,欢迎常来。

to newkid:有一个问题我很纳闷,就是我明明建立了两个字段的索引,
但是使用索引的时候却只能使用到第一个索引字段:
即:1.acess的时候只能使用第一个字段
    2.第二个字段是filter的,这个方案我试验了几次得出的。
    这里面的filter和acess,基本概念还是不是很清楚。
    我使用的降序索引是想索引按一个顺序去扫描,我是参照另一本书,但是给出的执行计划还是不懂。
   如果按照我的逻辑acess的时候是访问两个字段的,另外一个不应该是filter的。

使用道具 举报

回复

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

本版积分规则 发表回复

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