0
点赞
收藏
分享

微信扫一扫

201027:PowerDesigner使用-in,exists分析-vue调-Oracle中start with

暮晨夜雪 2021-09-28 阅读 58
每日复盘

一. PowerDesigner创建表

然后点击Columns,如下图设置,灰常简单,需要注意的就是P(primary主键) , F (foreign key外键) , M(mandatory强制性的,代表不可为空) 这三个,多看几遍理解其意思。

打开之后如图所示,修改好存在sql语句的位置和生成文件的名称即可

选定一个编辑的表,右键- >Properties- >Columns- >Customize Columns and Filter(或直接用快捷键Ctrl+U)- >Comment(前面打勾)- >OK

二. SQL中的in与not in、exists与not exists的区别以及性能分析

1. in和exists

in是把外表和内表作hash连接,而exists是对外表作loop循环,每次loop循环再对内表进行查询,一直以来认为exists比in效率高的说法是不准确的。如果查询的两个表大小相当,那么用in和exists差别不大;如果两个表中一个较小一个较大,则子查询表大的用exists,子查询表小的用in;

select * from A where cc in(select cc from B)  -->效率低,用到了A表上cc列的索引;
select * from A where exists(select cc from B where cc=A.cc)  -->效率高,用到了B表上cc列的索引。

相反的:

select * from B where cc in(select cc from A)  -->效率高,用到了B表上cc列的索引
select * from B where exists(select cc from A where cc=B.cc)  -->效率低,用到了A表上cc列的索引。

2. not in 和not exists

not in 逻辑上不完全等同于not exists,如果你误用了not in,小心你的程序存在致命的BUG,请看下面的例子:

create table #t1(c1 int,c2 int);
create table #t2(c1 int,c2 int);

insert into #t1 values(1,2);
insert into #t1 values(1,3);
insert into #t2 values(1,2);
insert into #t2 values(1,null);

select * from #t1 where c2 not in(select c2 from #t2);  -->执行结果:无
select * from #t1 where c2 not exists(select * from #t2 where #t2.c2=#t1.c2)  -->执行结果:1  3

正如所看到的,not in出现了不期望的结果集,存在逻辑错误。如果看一下上述两个select 语句的执行计划,也会不同,后者使用了hash_aj,所以,请尽量不要使用not in(它会调用子查询),而尽量使用not exists(它会调用关联子查询)。如果子查询中返回的任意一条记录含有空值,则查询将不返回任何记录。如果子查询字段有非空限制,这时可以使用not in,并且可以通过提示让它用hasg_aj或merge_aj连接。

如果查询语句使用了not in,那么对内外表都进行全表扫描,没有用到索引;而not exists的子查询依然能用到表上的索引。所以无论哪个表大,用not exists都比not in 要快

区别详情参考文章

三. Vue接口调用

//森林草原灭火-灭火作战次数走势
getFireFightingStatistics(data){
    return request({
        url: "/v1/command/getFireFightingStatistics",
        method: "get",
        params: data
    })
},

引入api

编写方法

async getSingleLineChartsData(conditon) {
    try {
        let resp = await GlassTaskApi.getFireFightingStatistics(conditon)
        let result = resp.data.result
        let data = {
            name: "灭火作战次数走势",
            xData: [],
            yData: []
        }
        result.forEach(e => {
            data.xData.push(e.NAME)
            data.yData.push(e.VALUE)
        })
        this.mhzzcszs = data
    } catch (e) {
        console.error(e)
    }
},

四. 如何使用start with connect by prior递归用法

为了能更好的介绍如何使用,首先需要创建一个测试表,然后结合例子来说明

create table t_menu
( menu_id varchar2(32),
  parent_id    varchar2(32));
insert into t_menu values ( '1', '' );
insert into t_menu values ( '2', '1' );
insert into t_menu values ( '3', '1' );
insert into t_menu values ( '4', '2' );
insert into t_menu values ( '5', '3' );
insert into t_menu values ( '6', '4' );
commit;
select * from t_menu;

创建了t_menu表,然后插入几条数据,再查询出表里数据

再来看下创建的表结构,为了简单,这里就只有两个字段,menu_id和parent_id

start with 递归查询起始条件

connect by 连接语句,后面加上连接的条件

为了演示向上和向下两个方向,我们这里选择menu_id为4的中间节点作为起始节点。

SELECT
    t.menu_id,
    t.parent_id,
    level
FROM
    t_menu t
START WITH
    t.menu_id = '4'
CONNECT BY
    t.parent_id = PRIOR  t.menu_id;

这里注意下PRIOR的位置,和menu_id放一起,表示向下查询

SELECT
    t.menu_id,
    t.parent_id,
    level
FROM
    t_menu t
START WITH
    t.menu_id = '4'
CONNECT BY
    PRIOR  t.parent_id = t.menu_id;

这里PRIOR和parent_id放一起,表示按照父节点方向,向上查询

SELECT
    t.menu_id,
    t.parent_id,
    level
FROM
    t_menu t
START WITH
    t.parent_id = '4'
CONNECT BY
    PRIOR  t.parent_id = t.menu_id;

START WITH后面的起始条件,换成parent_id,则可以从结果中看出,level为1级的则以parent_id字段为条件做为起始节点

以上的语句中,还可以添加where条件语句,这些条件是在递归查询的结果集中,再根据 where的条件进行筛选的。

举报

相关推荐

0 条评论