12
返回列表 发新帖
楼主: abc_gdong

字段多对多分类问题,求大神帮助

[复制链接]
论坛徽章:
44
秀才
日期:2016-04-29 15:03:39秀才
日期:2018-01-02 15:29:54秀才
日期:2018-01-02 15:29:54秀才
日期:2018-01-02 15:29:54秀才
日期:2018-01-02 15:35:05秀才
日期:2018-01-02 15:35:50秀才
日期:2018-01-02 15:35:50秀才
日期:2018-01-02 15:35:50状元
日期:2018-01-03 13:36:41榜眼
日期:2018-01-03 13:36:41
11#
 楼主| 发表于 2017-2-24 07:30 | 只看该作者
newkid 发表于 2017-2-24 05:55
分批commit是没有意义的。
此外不知道你的代码加在哪里,必须把完整的贴出来。

高亮部分是我修改的,代码如下:
create or replace procedure p1  is
    TYPE t_str IS TABLE OF VARCHAR2(1000) INDEX BY tmp_replacement.child%TYPE;
    parents t_str;

    TYPE t_num IS TABLE OF NUMBER INDEX BY tmp_replacement.child%TYPE;
    ranks t_num;

    TYPE t_result IS TABLE OF tmp_replacement%ROWTYPE INDEX BY PLS_INTEGER;
    v_result t_result;

    parentX tmp_replacement.node%TYPE;
    parentY tmp_replacement.node%TYPE;

    rankX int;
    rankY int;

    last_child tmp_replacement.child%TYPE;

    v_output t_str;

    vstr tmp_replacement.node%TYPE;

    FUNCTION find_parent(p_current IN tmp_replacement.node%TYPE)
    RETURN tmp_replacement.node%TYPE
    AS
    BEGIN
       IF parents(p_current)<>p_current THEN
          parents(p_current) :=find_parent(parents(p_current));
       END IF;
       RETURN parents(p_current);
    END find_parent;

BEGIN
    SELECT node, child,null BULK COLLECT INTO v_result
      FROM (SELECT LEAST(node,child) node,GREATEST(node, child) child FROM tmp_replacement
            UNION SELECT LEAST(node,child),LEAST(node,child) FROM tmp_replacement
           );

    FOR i IN 1..v_result.COUNT LOOP
        parents(v_result(i).node) := v_result(i).node;
        ranks(v_result(i).node) := 0;
    END LOOP;

    last_child :='*';

    FOR cur IN (select LEAST(node, child) AS node, GREATEST(node, child) AS child from tmp_replacement
                UNION SELECT LEAST(node,child),LEAST(node,child) FROM tmp_replacement
               order by 2,1)
    LOOP

        if cur.child <> last_child then
           -- find parent for x

           parentX := find_parent(cur.node);
           rankX := ranks(parentX);

           last_child := cur.child;
        ELSE

           -- find parent for y

           parentY := find_parent(cur.node);
           rankY := ranks(parentY);

           --- union x and y
           CASE
           WHEN parentX = parentY THEN
                continue;
           WHEN rankX < rankY THEN
                parents(parentX) := parentY;
                parentX := parentY;
                rankX := rankY;
           WHEN rankX > rankY THEN
                parents(parentY) := parentX;
           WHEN rankX = rankY THEN
                parents(parentY) := parentX;
                ranks(parentX) := ranks(parentX)+1;
           END CASE;
        END IF;

    END LOOP;

    FOR i IN 1..v_result.COUNT LOOP
        v_result(i).node := find_parent(v_result(i).node);
        update tmp_replacement set fz=v_result(i).node where node=v_result(i).child
        or child = v_result(i).child;
        IF (mod(i,2000)=0) THEN
          commit;
        END IF;
    END LOOP;
    commit;
END;

使用道具 举报

回复
论坛徽章:
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
12#
发表于 2017-2-24 11:40 | 只看该作者
这个相当于是计算完把结果写回去,没有问题。

使用道具 举报

回复
论坛徽章:
44
秀才
日期:2016-04-29 15:03:39秀才
日期:2018-01-02 15:29:54秀才
日期:2018-01-02 15:29:54秀才
日期:2018-01-02 15:29:54秀才
日期:2018-01-02 15:35:05秀才
日期:2018-01-02 15:35:50秀才
日期:2018-01-02 15:35:50秀才
日期:2018-01-02 15:35:50状元
日期:2018-01-03 13:36:41榜眼
日期:2018-01-03 13:36:41
13#
 楼主| 发表于 2017-2-24 20:19 | 只看该作者
newkid 发表于 2017-2-24 11:40
这个相当于是计算完把结果写回去,没有问题。

还有两个问题请教大师:
1、分批commit是没有意义的。怎么理解?
2、当数据量超过百万时,在循环中执行update语句的处理方式还可以优化吗?
谢谢!

使用道具 举报

回复
论坛徽章:
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
14#
发表于 2017-2-25 00:28 | 只看该作者
abc_gdong 发表于 2017-2-24 20:19
还有两个问题请教大师:
1、分批commit是没有意义的。怎么理解?
...

分批COMMIT破坏了事务的完整性。万一中途崩溃了,你的事情就做了一半。中途COMMIT也不会使得修改更快,反而会更慢,虽然差异是很小的。
如果数据量大,你可以采用FORALL来执行你的DML,而不是FOR循环。

使用道具 举报

回复
论坛徽章:
44
秀才
日期:2016-04-29 15:03:39秀才
日期:2018-01-02 15:29:54秀才
日期:2018-01-02 15:29:54秀才
日期:2018-01-02 15:29:54秀才
日期:2018-01-02 15:35:05秀才
日期:2018-01-02 15:35:50秀才
日期:2018-01-02 15:35:50秀才
日期:2018-01-02 15:35:50状元
日期:2018-01-03 13:36:41榜眼
日期:2018-01-03 13:36:41
15#
 楼主| 发表于 2017-2-25 09:20 | 只看该作者
newkid 发表于 2017-2-25 00:28
分批COMMIT破坏了事务的完整性。万一中途崩溃了,你的事情就做了一半。中途COMMIT也不会使得修改更快,反 ...

多谢!

使用道具 举报

回复

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

本版积分规则 发表回复

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