摘要:遍历字符串例如,把表的等于的字符串拆开来显示为行,每行一个字符。因此需要对空格进行处理。使用函数来将所有的字符按顺序串接起来最后只保留那些和原名字具有相同长度的字符串。经典实例第六章
遍历字符串
例如,把emp表的ename等于KING的字符串拆开来显示为4行,每行一个字符。
借助表t10:
select substr(e.ename, iter.pos, 1) as C from (select ename from emp where ename = "KING") e, (select id as pos from t10) iter where iter.pos <= length(e.ename);
其实看一下from语句的笛卡尔积就能理解:
select ename, iter.pos from (select ename from emp where ename = "KING") e, (select id as pos from t10) iter;嵌入引号
select "g""day mate" qmarks from t1 union all select "beavers""teeth" from t1 union all select """" from t1;统计字符出现的次数
select (length("HELLO HELLO") - length(replace("HELLO HELLO", "LL", "")))/length("LL") as cnt from t1;删除不想要的字符
例如,从emp表中的ename中删除元音字母,从sal中删除所有的0:
Oracle
select ename, replace(translate(ename, "AEIOU", "aaaaa"), "a", "") as stripped1, sal, replace(sal, 0, "") as stripped2 from emp;
MySQL没有提供translate函数,需要多次调用replace:
select ename, replace( replace( replace( replace( replace(ename, "A", ""), "E", ""), "I", ""), "O", ""), "U", "") as stripped1, sal, replace(sal, 0, "") as stripped2 from emp;分离数字和字符数据
考虑如下结果集:
select ename || cast(sal as char(4)) as data from emp;
想把数字和字母分开成两列。
Oracle
select replace( translate(data, "0123456789", "0000000000"), "0", "") ename, to_number( replace( translate(lower(data), "abcdefghijklmnopqrstuvwxyz", rpad("z", 26, "z")), "z")) sal from ( select ename || cast(sal as char(4)) data from emp ) x;
rpad函数从右边对字符串使用指定的字符进行填充
rpad(string,padded_length,[pad_string])
string 表示:被填充的字符串
padded_length 表示:字符的长度,是返回的字符串的数量,如果这个数量比原字符串的长度要短,rpad函数将会把字符串截取成从左到右的n个字符;
pad_string 是个可选参数,这个字符串是要粘贴到string的右边,如果这个参数未写,lpad函数将会在string的右边粘贴空格。
例如:
rpad("tech", 7); 将返回"tech " (后面有三个空格)
rpad("tech", 2); 将返回"te"
rpad("tech", 8, "0"); 将返回"tech0000"
rpad("tech on the net", 15, "z"); 将返回 "tech on the net" (原字符串一共15个,所以无需增加或者截取)
rpad("tech on the net", 16, "z"); 将返回 "tech on the netz"
考虑如下视图:
Oracle
create view V as select ename as data from emp where deptno = 10 union all select ename || ", $" || cast(sal as char(4)) || ".00" as data from emp where deptno = 20 union all select ename || cast(deptno as char(4)) as data from emp where deptno = 30;
MySQL
create view V as select ename as data from emp where deptno = 10 union all select concat(ename, ", $", sal, ".00") as data from emp where deptno = 20 union all select concat(ename, deptno) as data from emp where deptno = 30;
想要过滤那些包含了除字母和数字之外的结果:
Oracle
select data from V where translate(lower(data), "0123456789abcdefghijklmnopqrstuvwxyz ", rpad("a", 37, "a")) = rpad("a", length(data), "a");
MySQL
select data from V where data regexp "[^0-9a-zA-Z]" = 0;
注意,由于创建视图V时使用的是char(4),长度是固定的,所以当cast(deptno as char(4))长度不足4时会用空格补齐。因此需要对空格进行处理。原书p96语句有误
创建分隔列表考虑转换如下结果集:
select deptno, ename as emps from emp order by deptno;
变换成:
Oracle
select deptno, ltrim(sys_connect_by_path(ename, ","), ",") emps from ( select deptno, ename, row_number() over (partition by deptno order by empno) rn, count(*) over (partition by deptno) cnt from emp ) where level = cnt start with rn = 1 connect by prior deptno = deptno and prior rn = rn-1;
MySQL
select deptno, group_concat(ename order by empno separator ",") as emps from emp group by deptno;
GROUP_CONCAT函数可以完成所有的工作。它负责把传递给它的ENAME列拼接起来。它是一个聚合函数,所以查询语句需要用到GROUP_BY.
Oracle 语句分析:
考虑from子句的子查询:
select deptno, ename, row_number() over (partition by deptno order by empno) rn, count(*) over (partition by deptno) cnt from emp;按字母表顺序排列字符
考虑如下将ename按照字母顺序排列如下:
MySQL
select ename old_ename, group_concat(c order by c separator "") new_ename from ( select ename, substr(a.ename, iter.pos, 1) c from emp a, (select id pos from t10) iter where iter.pos <= length(a.ename) ) x group by ename;
考虑from子查询:
select ename, substr(a.ename, iter.pos, 1) c from emp a, (select id pos from t10) iter where iter.pos <= length(a.ename)
...
GROUP_CONCAT函数不仅能串接每个字母,还能按照字母表顺序对它们进行排序。
Oracle 使用SYS_CONNECT_BY_PATH函数迭代创建一个列表:
select old_name, new_name from ( select old_name, replace(sys_connect_by_path(c, " "), " ") new_name from ( select e.ename old_name, row_number() over (partition by e.ename order by substr(e.ename, iter.pos, 1)) rn, substr(e.ename, iter.pos, 1) c from emp e, (select rownum pos from emp) iter where iter.pos <= length(e.ename) order by 1 ) x start with rn=1 connect by prior rn = rn-1 and prior old_name = old_name ) where length(old_name) = length(new_name);
分析:看里层的子查询:
select e.ename old_name, row_number() over (partition by e.ename order by substr(e.ename, iter.pos, 1)) rn, substr(e.ename, iter.pos, 1) c from emp e, (select rownum pos from emp) iter where iter.pos <= length(e.ename) order by 1
...
然后,提取出排好序的字符并重建每个名字。使用SYS_CONNECT_BY_PATH函数来将所有的字符按顺序串接起来
select old_name, replace(sys_connect_by_path(c, " "), " ") new_name from ( select e.ename old_name, row_number() over (partition by e.ename order by substr(e.ename, iter.pos, 1)) rn, substr(e.ename, iter.pos, 1) c from emp e, (select rownum pos from emp) iter where iter.pos <= length(e.ename) order by 1 ) x start with rn=1 connect by prior rn = rn-1 and prior old_name = old_name
...
最后只保留那些和原名字具有相同长度的字符串。
考虑如下视图:
create view V as select "mo,larry,curly" as name from t1 union all select "tina,gina,jaunita,regina,leena" as name from t1;
希望提取每一行的第二个名字,解决问题的关键是把每一个名字转换为多带带的一行,并保持每一个名字在列表里的顺序不变。
MySQL
select name from ( select iter.pos, substring_index( substring_index(src.name, ",", iter.pos), ",", -1) name from V src, (select id pos from t10) iter where iter.pos <= length(src.name) - length(replace(src.name, ",", "")) ) x where pos = 2;
Oracle
select sub from ( select iter.pos, src.name, substr(src.name, instr(src.name, ",", 1, iter.pos) + 1, instr(src.name, ",", 1, iter.pos+1) - instr(src.name, ",", 1, iter.pos)-1) sub from (select ","||name||"," as name from V) src, (select rownum pos from emp) iter where iter.pos < length(src.name) - length(replace(src.name, ",")) ) where pos = 2;
《SQL经典实例》第六章
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/32308.html
摘要:哪吒社区技能树打卡打卡贴函数式接口简介领域优质创作者哪吒公众号作者架构师奋斗者扫描主页左侧二维码,加入群聊,一起学习一起进步欢迎点赞收藏留言前情提要无意间听到领导们的谈话,现在公司的现状是码农太多,但能独立带队的人太少,简而言之,不缺干 ? 哪吒社区Java技能树打卡 【打卡贴 day2...
摘要:依据子串排序从表检索员工的名字和职位,并且按照职位字段的最后两个字符对检索结果进行排序对含有字母和数字的列排序考虑如下视图以或者作为排序项。 依据子串排序 从emp表检索员工的名字和职位,并且按照职位字段的最后两个字符对检索结果进行排序MySQL & Oracle select ename, job from emp order by substr(job, length(...
摘要:计算平均值需要注意值的问题。例如考虑如下表如果采用如下查询得到函数会忽略值。累计求和计算全体员工工资的累计额。 计算平均值 需要注意null值的问题。例如考虑如下表: create table t2(sal integer); insert into t2 values(10); insert into t2 values(20); insert into t2 values(null...
摘要:桥接模式定义桥接模式定义抽象化角色它的主要职责是定义出该角色的行为,同时保存一个对实现化角色的引用,该角色一般是抽象类。这种优雅的实现数据库切换方式就是利用了桥接模式。1、什么是桥接模式?Decouple an abstraction from its implementation so that the two can vary independently.桥接模式(Bridge Patt...
摘要:列举模式中的表列举字段列举索引列列举约束列举非索引外键列出含有非索引外键的表。例如,希望确认表的外键是否加入了索引描述数据字典视图查询视图,并列出数据字典视图及其目的查询并找出某个数据字典视图的各列含义经典实例第五章 列举模式中的表 Oracle select table_name from all_tables where owner = SCOTT; showImg(ht...
阅读 3284·2023-04-25 19:56
阅读 1428·2021-11-12 10:36
阅读 1543·2021-11-08 13:19
阅读 1364·2019-08-30 14:06
阅读 2842·2019-08-30 11:01
阅读 1569·2019-08-29 13:23
阅读 2570·2019-08-29 11:18
阅读 3293·2019-08-26 13:35