巧用数据库的遍历
来源:互联网 发布:投诉淘宝店铺有用吗 编辑:程序博客网 时间:2024/05/01 02:30
问题描述:
这是一个古老的问题,
supplier 有多个products,
需求,为每个product 找属于同一个supplier 的3个兄弟products(不能是自己).
如果少于3个,有几个就找几个。
my senior的做法:
对每个product, 从头开始找3个product(非自己就可以),
出现问题:因为每个product 每次都要从头开始找,每次找到,还要与自己比较3次,
当product足够多的时候,程序就崩溃了。
解决办法:
利用SQL/PLUS,开cursor, go through 一遍,每个product的兄弟用它前面的三个;最前面的那个三个呢,
第一个的兄弟是最后的三个;第二个的是,最后两个和第一个;第三个的是最后一个和第1,2。
如果是少于三个,同理类推。
code 如下:(只有一个brother的情况)
SET VERIFY OFF
DECLARE
preSuppId NUMBER DEFAULT 0;
pre_ppId1 NUMBER DEFAULT 0;
pre_ppId2 NUMBER DEFAULT 0;
pre_ppId3 NUMBER DEFAULT 0;
first_ppId NUMBER DEFAULT 0;
second_ppId NUMBER DEFAULT 0;
third_ppId NUMBER DEFAULT 0;
cur_ppId NUMBER DEFAULT 0;
cur_suppId NUMBER DEFAULT 0;
num NUMBER DEFAULT 0;
CURSOR cur IS
SELECT SUPPLIER_ID cur_suppId,PRODUCT_ID cur_ppId FROM product_funnel WHERE SUPPLIER_PDT_CNT =2 order by supplier_id ;
BEGIN
for rec in cur LOOP
IF preSuppId<>rec.cur_suppId THEN
--num<>0 means need to process last supplier's first 3 record update
IF num<>0 THEN
UPDATE product_funnel_ranking pfr
SET pfr.related_product_id1 = pre_ppId1
WHERE pfr.product_id = first_ppId;
num := 0;
END IF;
--num = 0, means, start one new supplier
IF num=0 THEN
pre_ppId1 := rec.cur_ppId;
num := 1;
preSuppId := rec.cur_suppId;
first_ppId := rec.cur_ppId;
END IF;
-- the same supplier ,need to check num.if num <3 ,means processing the first 3 record,
-- if num =3, update the current record
ELSE
IF num=1 THEN
UPDATE product_funnel_ranking pfr
SET pfr.related_product_id1 = pre_ppId1
WHERE pfr.product_id = rec.cur_ppId;
pre_ppId1 := rec.cur_ppId;
END IF;
END IF;
END LOOP;
--update the last second rec
UPDATE product_funnel_ranking pfr
SET pfr.related_product_id1 = pre_ppId1
WHERE pfr.product_id = first_ppId;
commit;
END;
/
EXIT;
效果:20W数据,最快可以跑4分钟。
relatePDT1,relatePDT2,relatePDT3;分别建立index (原来就有的, 原因??)
下图给出两个例子:
note:
1. this method is better than old one , can be a smart way to resolve currnet problem.
2.可以考虑function ,but 逻辑简单,考虑到function占用oracle server 空间,没用
这是一个古老的问题,
supplier 有多个products,
需求,为每个product 找属于同一个supplier 的3个兄弟products(不能是自己).
如果少于3个,有几个就找几个。
my senior的做法:
对每个product, 从头开始找3个product(非自己就可以),
出现问题:因为每个product 每次都要从头开始找,每次找到,还要与自己比较3次,
当product足够多的时候,程序就崩溃了。
解决办法:
利用SQL/PLUS,开cursor, go through 一遍,每个product的兄弟用它前面的三个;最前面的那个三个呢,
第一个的兄弟是最后的三个;第二个的是,最后两个和第一个;第三个的是最后一个和第1,2。
如果是少于三个,同理类推。
code 如下:(只有一个brother的情况)
SET VERIFY OFF
DECLARE
preSuppId NUMBER DEFAULT 0;
pre_ppId1 NUMBER DEFAULT 0;
pre_ppId2 NUMBER DEFAULT 0;
pre_ppId3 NUMBER DEFAULT 0;
first_ppId NUMBER DEFAULT 0;
second_ppId NUMBER DEFAULT 0;
third_ppId NUMBER DEFAULT 0;
cur_ppId NUMBER DEFAULT 0;
cur_suppId NUMBER DEFAULT 0;
num NUMBER DEFAULT 0;
CURSOR cur IS
SELECT SUPPLIER_ID cur_suppId,PRODUCT_ID cur_ppId FROM product_funnel WHERE SUPPLIER_PDT_CNT =2 order by supplier_id ;
BEGIN
for rec in cur LOOP
IF preSuppId<>rec.cur_suppId THEN
--num<>0 means need to process last supplier's first 3 record update
IF num<>0 THEN
UPDATE product_funnel_ranking pfr
SET pfr.related_product_id1 = pre_ppId1
WHERE pfr.product_id = first_ppId;
num := 0;
END IF;
--num = 0, means, start one new supplier
IF num=0 THEN
pre_ppId1 := rec.cur_ppId;
num := 1;
preSuppId := rec.cur_suppId;
first_ppId := rec.cur_ppId;
END IF;
-- the same supplier ,need to check num.if num <3 ,means processing the first 3 record,
-- if num =3, update the current record
ELSE
IF num=1 THEN
UPDATE product_funnel_ranking pfr
SET pfr.related_product_id1 = pre_ppId1
WHERE pfr.product_id = rec.cur_ppId;
pre_ppId1 := rec.cur_ppId;
END IF;
END IF;
END LOOP;
--update the last second rec
UPDATE product_funnel_ranking pfr
SET pfr.related_product_id1 = pre_ppId1
WHERE pfr.product_id = first_ppId;
commit;
END;
/
EXIT;
效果:20W数据,最快可以跑4分钟。
relatePDT1,relatePDT2,relatePDT3;分别建立index (原来就有的, 原因??)
下图给出两个例子:
note:
1. this method is better than old one , can be a smart way to resolve currnet problem.
2.可以考虑function ,but 逻辑简单,考虑到function占用oracle server 空间,没用
- 巧用数据库的遍历
- 遍历数据库的表结构
- 数据库的增删改查加遍历
- 遍历数据库
- 数据库遍历
- TreeView (树视图)遍历数据库的方法
- TreeView (树视图)遍历数据库的方法
- 数据库中实现二叉树的遍历
- PHP数据库树的遍历方法
- 遍历数据库中两个数据表的方法
- 以遍历的形式读取HBase数据库
- C#遍历数据库中的表的名字
- 利用ssh遍历数据库的奇技淫巧
- 用游标遍历某台服务器下所有的数据库中某个字段所在的表名及数据库名
- 数据库中取出数据用什么算法遍历它的子节点
- 纯ajax遍历数据库 遍历数据库字段
- struts2标签的遍历数据库查询后的数组list
- 遍历mysql中所有的数据库和所有的表
- 莫名的文件被占用
- dwr.xml 配置
- spring中五种自动装配的区别及依赖检查模式的应用
- 动态域名解析新手上路
- 给对话框添加菜单 工具栏 状态栏简易方法
- 巧用数据库的遍历
- “稻草人”动态域名解析服务
- 提供个解决微软20日的黑屏行为方法:
- Linux内核复习之分段机制
- 刚看完TC++PL的第二部分
- Eclipse插件使用links目录的用法:
- Linux内核复习之分页机制
- web版注入工具(asp+mssql)beta 3 final release
- SQL重复记录查询