SQLCOOK教程笔记(第一章-第七章)

此书及其相关脚本下载方法:关注微信公众号,点击功能介绍-书籍链接下载,即可获取

SQLCOOK教程笔记

1.检索记录

--1.1从表中检索所有行列
SELECT * FROM hyz_emp;
--1.2从表中检索部分行
SELECT * FROM hyz_emp s WHERE s.deptno = 10;
--1.3查找满足多个条件的行
SELECT *
  FROM hyz_emp s
 WHERE s.deptno = 10 --deptno=10
    OR s.comm IS NOT NULL --或comm不是NULL
    OR s.sal <= 2000 --或sal小于2000
   AND s.deptno = 20 --并且deptno=20
;
/*1.3.1等同于*/
SELECT *
  FROM hyz_emp s
 WHERE (s.deptno = 10 --deptno=10或comm不是NULL
       OR s.comm IS NOT NULL)
    OR (s.sal <= 2000 --或sal小于2000并且deptno=20
       AND s.deptno = 20);
/*1.3.2等同于*/
SELECT *
  FROM hyz_emp s
 WHERE (s.deptno = 10 --deptno=10或comm不是NULL
       OR s.comm IS NOT NULL)
UNION
SELECT *
  FROM hyz_emp s
 WHERE (s.sal <= 2000 --sal小于2000并且deptno=20
       AND s.deptno = 20);
/*1.3.3如果用此括号方式,含义就不一样了*/
SELECT *
  FROM hyz_emp s
 WHERE (s.deptno = 10 --deptno=20中存在deptno=10或comm不是NULL或sal小于2000
       OR s.comm IS NOT NULL OR s.sal <= 2000)
   AND s.deptno = 20;
/*1.3.4查看deptno = 20结果,很明显不能满足deptno=10,也不能满足comm不是NULL,
但是满足了sal小于2000存在两条,所以得出1.3.3代码中最终显示结果*/
SELECT * FROM hyz_emp s WHERE s.deptno = 20;
--1.4从表中检索部分列
SELECT s.ename, s.deptno, s.sal FROM hyz_emp s; --这样可以不用返回多余字段,也可以节约时间
--1.5为列取有意义的名称
SELECT s.sal AS 工资, s.comm AS 奖金 FROM hyz_emp s;
--1.6在WHERE子句中引用取别名的列
SELECT *
  FROM (SELECT s.sal AS 工资, s.comm AS 奖金 FROM hyz_emp s) k
 WHERE k.奖金 IS NOT NULL
   AND k.工资 = 1250;
--1.7连接列值s
SELECT s.ename || '的工作是' || decode(s.mgr,
                                   NULL,
                                   '董事长',
                                   decode(s.job,
                                          '会计',
                                          '员工',
                                          '研究员',
                                          '员工',
                                          '销售员',
                                          '员工',
                                          '操作员',
                                          '员工')) AS ename_job,
       s.mgr
  FROM hyz_emp s;
--1.8在select语句中使用条件逻辑
SELECT s.ename,
       s.sal,
       (CASE
         WHEN s.sal <= 2000 THEN
          '所得报酬过低'
         WHEN s.sal >= 4000 THEN
          '所得报酬过高'
         ELSE
          '一般'
       END) AS status --状态
  FROM hyz_emp s;
--1.9限制返回的行数
SELECT * FROM hyz_emp s WHERE rownum <= 5;
--1.10从表中随机返回n条记录
SELECT ename, job
  FROM (SELECT s.ename, s.job FROM hyz_emp s ORDER BY dbms_random.value()) k
 WHERE rownum <= 5;
--1.11查找空值
SELECT *
  FROM hyz_emp s
 WHERE s.comm IS NULL
   AND s.mgr IS NOT NULL;
--1.12将空值转换为实际值
SELECT coalesce(s.comm, 0) AS comm FROM hyz_emp s; --从左往右数,遇到第一个非null值,则返回该非null值。
/*等同于
*/
SELECT nvl(s.comm, 0) AS comm FROM hyz_emp s; --如果第一个参数为null,则返回第二个参数,反之返回第一个参数
/*第一点区别:nvl只适合于两个参数的,COALESCE适合于多个参数。
第二点区别:COALESCE里的所有参数类型必须保持一致,nvl可以不一致。*/
--1.13按模式搜索
SELECT s.ename, s.job FROM hyz_emp s WHERE s.deptno IN (10, 20);
SELECT s.ename, s.job
  FROM hyz_emp s
 WHERE s.deptno IN (10, 20)
   AND (s.ename LIKE '%俊明%' OR s.ename LIKE '%乾');

2.查询结果排序

--2.1以指定的次序返回查询结果
SELECT s.ename, s.job, s.sal
  FROM hyz_emp s
 WHERE s.deptno = 10
 ORDER BY s.sal ASC; --升序
SELECT s.ename, s.job, s.sal
  FROM hyz_emp s
 WHERE s.deptno = 10
 ORDER BY s.sal DESC; --降序
SELECT s.ename, s.job, s.sal
  FROM hyz_emp s
 WHERE s.deptno = 10
 ORDER BY 3 ASC; --可以使用数字,但是不推荐
--2.2按多个字段排序
SELECT s.ename, s.deptno, s.job, s.sal
  FROM hyz_emp s
 WHERE s.deptno = 10
 ORDER BY s.deptno, s.sal DESC;
--2.3按子串排序
SELECT s.ename, s.job
  FROM hyz_emp s
 ORDER BY substr(s.job, length(s.job) - 2);
--2.4对字母数字混合的数据排序
SELECT s.ename || ' ' || s.deptno AS data FROM hyz_emp s;
/*order by hyz_deptno*/
SELECT s.ename || ' ' || s.deptno AS data
  FROM hyz_emp s
 ORDER BY REPLACE(data,
                  REPLACE(translate(data, '0123456789', '#########'),
                          '#',
                          ''),
                  '');
SELECT s.ename || ' ' || s.deptno AS data
  FROM hyz_emp s
 ORDER BY regexp_substr(data, '[0-9]+') ASC;
/*order by ename*/
SELECT s.ename || ' ' || s.deptno AS data
  FROM hyz_emp s
 ORDER BY REPLACE(translate(data, '0123456789', '#########'), '#', '');
SELECT s.ename || ' ' || s.deptno AS data
  FROM hyz_emp s
 ORDER BY regexp_substr(data, '[[:alnum:]]+') ASC;
--2.5处理排序空值
SELECT s.ename,
       s.sal,
       s.comm,
       (CASE
         WHEN s.comm IS NULL THEN
          0
         ELSE
          1
       END) AS is_null
  FROM hyz_emp s;
--2.6根据数据项的键排序  
SELECT s.ename,
       s.sal,
       s.comm,
       (CASE
         WHEN s.comm IS NULL THEN
          s.sal
         ELSE
          s.comm
       END) AS ordered,
       s.*
  FROM hyz_emp s
 ORDER BY ordered;

3.操作多个表

--3.1记录集的叠加
SELECT s.ename, s.sal, s.comm, s.deptno
  FROM hyz_emp s
 WHERE s.deptno = 10
UNION ALL --并集,不去除重复
SELECT s.ename, s.sal, s.comm, s.deptno
  FROM hyz_emp s;
SELECT s.ename, s.sal, s.comm, s.deptno
  FROM hyz_emp s
 WHERE s.deptno = 10
UNION --并集,去除重复
SELECT s.ename, s.sal, s.comm, s.deptno
  FROM hyz_emp s;
SELECT s.ename, s.sal, s.comm, s.deptno FROM hyz_emp s;
SELECT s.ename, s.sal, s.comm, s.deptno
  FROM hyz_emp s
 WHERE s.deptno = 10
INTERSECT --交集
SELECT s.ename, s.sal, s.comm, s.deptno
  FROM hyz_emp s;
SELECT s.ename, s.sal, s.comm, s.deptno
  FROM hyz_emp s
 WHERE s.deptno = 10
MINUS --差集
SELECT s.ename, s.sal, s.comm, s.deptno
  FROM hyz_emp s;
--3.2组合相关的行
SELECT e.ename, d.loc, e.*, d.*
  FROM hyz_emp e, hyz_dept d
 WHERE e.deptno = d.deptno --防止笛卡儿积
   AND e.deptno = 10;
/*等同于*/
SELECT e.ename, d.loc, e.*, d.*
  FROM hyz_emp e
  JOIN hyz_dept d
    ON e.deptno = d.deptno --防止笛卡儿积
   AND e.deptno = 10;
--3.3在两个表中查找共同行
SELECT s.ename, s.sal, s.comm, s.deptno
  FROM hyz_emp s
 WHERE s.deptno = 10
INTERSECT --交集
SELECT s.ename, s.sal, s.comm, s.deptno
  FROM hyz_emp s;
/*等同于*/
SELECT s.ename, s.sal, s.comm, s.deptno
  FROM hyz_emp s
  JOIN hyz_emp o
    ON s.empno = o.empno
   AND s.ename = o.ename
   AND s.job = o.job
 WHERE s.deptno = 10;
--3.4从一个表中查找另一个表没有的值
CREATE OR REPLACE view sqlcook_emp_3_4 AS
  SELECT s.ename, s.sal, s.comm, s.deptno + 1 AS deptno
    FROM hyz_emp s
   WHERE s.deptno = 10;
SELECT s.ename, s.sal, s.comm, s.deptno AS deptno
  FROM sqlcook_emp_3_4 s
 WHERE s.deptno = 11
MINUS --差集
SELECT s.ename, s.sal, s.comm, s.deptno
  FROM hyz_emp s;
/*等同于*/
SELECT s.ename, s.sal, s.comm, s.deptno AS deptno
  FROM sqlcook_emp_3_4 s
 WHERE s.deptno = 11
   AND NOT EXISTS
 (SELECT t.deptno FROM hyz_emp t WHERE s.deptno = t.deptno);
--3.5在一个表中查找与其他表不匹配的记录
SELECT * FROM hyz_emp;
SELECT *
  FROM hyz_dept d
  JOIN hyz_emp e
    ON d.deptno = e.deptno(+)
   AND e.deptno IS NULL;
--3.6向查询中增加联接而不影响其他联接
SELECT e.*, d.* FROM hyz_dept d LEFT JOIN hyz_emp e ON e.deptno = d.deptno;
--3.7检测两个表中是否有相同的数据
CREATE OR REPLACE view sqlcook_emp_3_6 AS
  SELECT *
    FROM hyz_emp s
   WHERE s.deptno != 10
  UNION ALL
  SELECT *
    FROM hyz_emp s
   WHERE s.ename = '乐正开济';

(
  SELECT s.empno,
         s.ename,
         s.job,
         s.mgr,
         s.hiredate,
         s.sal,
         s.comm,
         s.deptno,
         COUNT(*) AS n
    FROM hyz_emp s
   GROUP BY s.empno,
            s.ename,
            s.job,
            s.mgr,
            s.hiredate,
            s.sal,
            s.comm,
            s.deptno
  MINUS
  SELECT s.empno,
         s.ename,
         s.job,
         s.mgr,
         s.hiredate,
         s.sal,
         s.comm,
         s.deptno,
         COUNT(*) AS n
    FROM sqlcook_emp_3_6 s
   GROUP BY s.empno,
            s.ename,
            s.job,
            s.mgr,
            s.hiredate,
            s.sal,
            s.comm,
            s.deptno)
  UNION (SELECT s.empno,
                s.ename,
                s.job,
                s.mgr,
                s.hiredate,
                s.sal,
                s.comm,
                s.deptno,
                COUNT(*) AS n
           FROM sqlcook_emp_3_6 s
          GROUP BY s.empno,
                   s.ename,
                   s.job,
                   s.mgr,
                   s.hiredate,
                   s.sal,
                   s.comm,
                   s.deptno
         MINUS
         SELECT s.empno,
                s.ename,
                s.job,
                s.mgr,
                s.hiredate,
                s.sal,
                s.comm,
                s.deptno,
                COUNT(*) AS n
           FROM hyz_emp s
          GROUP BY s.empno,
                   s.ename,
                   s.job,
                   s.mgr,
                   s.hiredate,
                   s.sal,
                   s.comm,
                   s.deptno);
--3.8识别和消除笛卡儿积
SELECT e.ename, d.loc
  FROM hyz_emp e
  JOIN hyz_dept d
    ON e.deptno = d.deptno
   AND e.deptno = 10;
--3.9聚集和联接
CREATE OR REPLACE view sqlcook_emp_3_9 AS
  SELECT s.empno,
         s.hiredate AS received,
         (CASE
           WHEN s.sal <= 800 THEN
            1
           WHEN s.sal BETWEEN 801 AND 1999 THEN
            2
           WHEN s.sal BETWEEN 2000 AND 5000 THEN
            3
           ELSE
            4
         END) AS TYPE
    FROM hyz_emp s;
SELECT DISTINCT deptno, total_sal, total_bonus
  FROM (SELECT e.empno,
               e.ename,
               SUM(DISTINCT e.sal) over(PARTITION BY deptno) AS total_sal,
               e.deptno,
               SUM(e.sal * (CASE
                     WHEN eb.type = 1 THEN
                      0.1
                     WHEN eb.type = 2 THEN
                      0.2
                     WHEN eb.type = 3 THEN
                      0.3
                     ELSE
                      0.4
                   END)) over(PARTITION BY deptno) AS total_bonus
          FROM hyz_emp e
          JOIN sqlcook_emp_3_9 eb
            ON e.empno = eb.empno
           AND e.deptno = 10) x; --1614898
SELECT SUM(DISTINCT s.sal) AS total_sal FROM hyz_emp s WHERE s.deptno = 10; --1614898
--3.10聚集和外联接
SELECT DISTINCT deptno, total_sal, total_bonus
  FROM (SELECT e.empno,
               e.ename,
               SUM(DISTINCT e.sal) over(PARTITION BY deptno) AS total_sal,
               e.deptno,
               SUM(e.sal * (CASE
                     WHEN eb.type = 1 THEN
                      0.1
                     WHEN eb.type = 2 THEN
                      0.2
                     WHEN eb.type = 3 THEN
                      0.3
                     ELSE
                      0.4
                   END)) over(PARTITION BY deptno) AS total_bonus
          FROM hyz_emp e
          JOIN sqlcook_emp_3_9 eb
            ON e.empno = eb.empno(+)
           AND e.deptno = 10) x; --1614898
--3.11从多个表中返回丢失的数据
SELECT d.deptno, d.dname, e.ename, e.deptno
  FROM hyz_dept d
  JOIN hyz_emp e
    ON d.deptno = e.deptno(+)
   AND e.deptno IS NULL
UNION
SELECT d.deptno, d.dname, e.ename, e.deptno
  FROM hyz_dept d
  JOIN hyz_emp e
    ON d.deptno(+) = e.deptno
   AND e.deptno IS NULL;
--3.12在运算和比较时使用NULL值
SELECT s.ename, s.comm, coalesce(s.comm, 0) AS comm
  FROM hyz_emp s
 WHERE coalesce(s.comm, 0) <
       (SELECT comm FROM hyz_emp WHERE ename = '雷立诚');

4.插入,更新与删除

--4.1插入新记录
INSERT INTO hyz_dept
  (deptno, total_sal, total_bonus)
VALUES
  (60, '业务员', '江苏');
COMMIT;
--4.2插入默认值
INSERT INTO hyz_emp (empno, comm) VALUES (0, DEFAULT);
ROLLBACK;
--4.3用NULL值代替默认值
INSERT INTO hyz_emp (empno, comm) VALUES (0, NULL);
ROLLBACK;
--4.4从一个表中从另一个表中复制行
INSERT INTO hyz_dept
  (deptno, dname, loc)
  SELECT s.deptno + 40, s.dname, s.loc
    FROM hyz_dept s
   WHERE s.loc IN ('深圳', '广州');
ROLLBACK;
--4.5复制表定义
CREATE TABLE bonus AS
  SELECT * FROM hyz_bonus s WHERE 0 = 1;
SELECT * FROM bonus;
drop TABLE bonus;
--4.6一次向多个表中插入记录
CREATE TABLE dept_east AS --东
  SELECT * FROM hyz_dept s WHERE 0 = 1;
CREATE TABLE dept_north AS --北
  SELECT * FROM hyz_dept s WHERE 0 = 1;
CREATE TABLE dept_south AS --南
  SELECT * FROM hyz_dept s WHERE 0 = 1;
CREATE TABLE dept_west AS --西
  SELECT * FROM hyz_dept s WHERE 0 = 1;
INSERT ALL WHEN loc IN
  ('上海', '江苏') THEN INTO dept_east
  (deptno, dname, loc)
VALUES
  (deptno, dname, loc) WHEN loc = '北京' THEN INTO dept_north
  (deptno, dname, loc)
VALUES
  (deptno, dname, loc) WHEN loc IN
  ('湖南', '深圳', '广州') THEN INTO dept_south
  (deptno, dname, loc)
VALUES
  (deptno, dname, loc) ELSE INTO dept_west
  (deptno, dname, loc)
VALUES
  (deptno, dname, loc)
  SELECT deptno, dname, loc FROM hyz_dept;
COMMIT;
SELECT * FROM dept_east; --东
SELECT * FROM dept_south; --南
SELECT * FROM dept_west; --西
SELECT * FROM dept_north; --北
drop TABLE dept_east; --东
drop TABLE dept_south; --南
drop TABLE dept_west; --西
drop TABLE dept_north; --北
--4.7阻止对某几列插入
/*创建视图,视图的插入只适用于简单的视图,它实际上会转换插入到原表*/
CREATE OR REPLACE view sqlcook_emp_4_7 AS
  SELECT empno, ename, job FROM hyz_emp;
SELECT * FROM sqlcook_emp_4_7;
INSERT INTO sqlcook_emp_4_7
  (empno, ename, job)
VALUES
  (0, '二次猿', '会计');
ROLLBACK;
--4.8在表中编辑记录
SELECT * FROM hyz_emp;
UPDATE hyz_emp s SET s.sal = s.sal * 1.1 WHERE s.deptno = 10;
ROLLBACK;
--4.9当对应行存在时更新
SELECT * FROM hyz_emp;
SELECT * FROM hyz_bonus;
UPDATE hyz_emp
   SET sal = sal * 1.3
 WHERE EXISTS (SELECT s.job FROM hyz_bonus s WHERE s.job = job);
ROLLBACK;
--4.10用其他的表中的值更新
SELECT s.empno, s.ename, s.job, s.mgr, s.hiredate, s.sal, s.comm, s.deptno
  FROM hyz_emp s;
SELECT s.deptno, s.dname, s.loc FROM hyz_dept s;
UPDATE (SELECT s.empno,
               s.ename,
               s.deptno AS emp_deptno,
               o.deptno AS deptno,
               s.job    AS job,
               o.dname  AS dname,
               o.loc    AS loc
          FROM hyz_emp s
          JOIN hyz_dept o
            ON s.deptno = o.deptno)
   SET emp_deptno = deptno, job = dname;
ROLLBACK;
--4.11合并记录
CREATE TABLE sqlcook_emp_4_11 AS
  SELECT s.deptno, s.empno, s.ename, s.comm
    FROM hyz_emp s
   WHERE s.deptno = 10;
SELECT s.deptno, s.empno, s.ename, s.comm FROM sqlcook_emp_4_11 s;
MERGE INTO sqlcook_emp_4_11 ec
USING (SELECT * FROM hyz_emp) emp
ON (ec.empno = emp.empno)
WHEN MATCHED THEN
  UPDATE SET ec.comm = 1000 DELETE WHERE (emp.sal < 2000)
WHEN NOT MATCHED THEN
  INSERT
    (ec.empno, ec.ename, ec.deptno, ec.comm)
  VALUES
    (emp.empno, emp.ename, emp.deptno, emp.comm);
COMMIT;
SELECT s.deptno, s.empno, s.ename, s.comm FROM hyz_emp s;
--4.12从表中删除所有记录
DELETE FROM hyz_emp;
ROLLBACK;
--4.13从表中删除指定记录
DELETE FROM hyz_emp s WHERE s.deptno = 10;
ROLLBACK;
--4.14删除单个记录
DELETE FROM hyz_emp s WHERE s.empno = 2017;
ROLLBACK;
--4.15删除违反参照完整性的记录
DELETE hyz_emp s
 WHERE EXISTS (SELECT o.deptno FROM hyz_dept o WHERE s.deptno = o.deptno);
ROLLBACK;
--4.16删除重复记录
SELECT s.empno, s.job FROM hyz_emp s;
SELECT MIN(s.empno), s.job FROM hyz_emp s GROUP BY s.job;
DELETE hyz_emp s
 WHERE s.empno NOT IN (SELECT MIN(s.empno) FROM hyz_emp s GROUP BY s.job);
ROLLBACK;
--4.17删除从其他表引用的记录
DELETE hyz_emp s
 WHERE s.deptno IN (SELECT o.deptno
                      FROM hyz_dept o
                    HAVING COUNT(*) = 1
                     GROUP BY o.deptno);
ROLLBACK;

5.元数据查询

--5.1列出模式中的表
SELECT s.table_name FROM all_tables s WHERE s.owner = 'HUYINGZHAO';
--5.2列出表中的列
SELECT s.column_name, s.data_type, s.column_id
  FROM all_tab_columns s
 WHERE s.owner = 'HUYINGZHAO'
   AND s.table_name = 'HYZ_EMP';
--5.3列出表中的索引列
SELECT s.table_name, s.index_name, s.column_name, s.column_position
  FROM all_ind_columns s
 WHERE s.table_name = 'HYZ_EMP'
   AND s.table_owner = 'HUYINGZHAO';
--5.4列出表中的约束
SELECT a.table_name, a.constraint_name, b.column_name, a.constraint_type
  FROM all_constraints a
  JOIN all_cons_columns b
    ON a.owner = b.owner
   AND a.table_name = b.table_name
   AND a.constraint_name = b.constraint_name
 WHERE a.table_name = 'HYZ_EMP'
   AND a.owner = 'HUYINGZHAO';
--5.5列出没有相应索引的外键
SELECT a.table_name,
       a.constraint_name,
       a.column_name,
       c.index_owner,
       c.index_name
  FROM all_cons_columns a, all_constraints b, all_ind_columns c
 WHERE a.owner = b.owner
   AND a.table_name = b.table_name
   AND a.constraint_name = b.constraint_name
   AND a.owner = c.table_owner(+)
   AND a.table_name = c.table_name(+)
   AND a.column_name = c.column_name(+)
   AND c.index_owner IS NULL
   AND a.owner = 'HUYINGZHAO'
   AND a.table_name = 'HYZ_EMP'
   AND b.constraint_type = 'R';
--5.6使用SQL来生成SQL
SELECT 'select count(*) from ' || s.table_name || ';' FROM user_tables s;
--5.7在ORACLE中描述数据字典视图
SELECT s.column_name, s.comments
  FROM dict_columns s
 WHERE s.table_name = 'ALL_TAB_COLUMNS';

6.使用字符串

SELECT 'g''day mate' q FROM dual;
SELECT 'beavers'' teeth' FROM dual;
SELECT '''' FROM dual;
SELECT q'{hell'o}' AS q FROM dual;
SELECT q'[hell'o]' AS q FROM dual;
SELECT q'(hell'o)' AS q FROM dual;
--6.3计算字符在字符串出现的次数
SELECT (length('HELLO HELLO') - length(REPLACE('HELLO HELLO', 'LL', ''))) /
       length('LL') AS h
  FROM dual;
--6.4从字符串中删除不需要的字符
--'a'起到占位符.无实际意义
SELECT ename,
       REPLACE(translate(ename, 'AEIOU', 'a'), 'a') AS stripped1,
       sal,
       REPLACE(sal, 0, '') AS stripped2
  FROM scott.emp;
SELECT REPLACE(translate('EAECOUUUU', 'AEIOU', 'a'), 'a') AS stripped1
  FROM dual;
--第六章后面几乎可以用正则表达式代替,可以略过

7.使用数字

--7.1计算平均值
SELECT AVG(s.mgr) FROM scott.emp s;
--7.2求某列的最大值/最小值
SELECT MAX(s.sal), MIN(s.mgr) FROM scott.emp s;
--7.3对某列的值求和
SELECT SUM(sal) FROM hyz_emp;
--7.4求一个表的行数
SELECT COUNT(*) FROM hyz_emp; --如果此列所有字段都为NULL,会忽略为NULL的列,9999
--7.5求某列值的个数
SELECT COUNT(s.comm) FROM hyz_emp s; --如果指定字段的值为NULL,会忽略为NULL的列,9975
--7.6生成累计和
SELECT empno,
       sal,
       SUM(sal) over(ORDER BY sal, empno) AS running_totdal1,
       SUM(sal) over(ORDER BY sal) AS running_totdal2
  FROM hyz_emp
 ORDER BY 2;
--7.7生成累乘积
--此函数为0和负数无法正常输出
SELECT s.empno,
       s.ename,
       s.sal,
       exp(SUM(ln(s.sal)) over(ORDER BY s.sal, s.empno)) AS running_prod
  FROM hyz_emp s
 WHERE s.deptno = 10;
--可包含0和负数的,只取负数
SELECT empno, ename, sal, tmp AS running_prod
  FROM (SELECT empno, ename, -sal AS sal FROM hyz_emp WHERE deptno = 10) model dimension BY(row_number() over(ORDER BY sal DESC) rn) measures(sal, 0 tmp, empno, ename) rules(tmp [ ANY ] = (CASE
         WHEN sal [
          cv() - 1
          ] IS NULL THEN
          sal [ cv() ]
         ELSE
          tmp [
          cv() - 1
          ] * sal [ cv() ]
       END));
--7.8计算累计差
SELECT ename,
       sal,
       SUM((CASE
             WHEN rn = 1 THEN
              sal
             ELSE
              -sal
           END)) over(ORDER BY sal, empno) AS running_diff
  FROM (SELECT empno,
               ename,
               sal,
               row_number() over(ORDER BY sal, empno) AS rn
          FROM hyz_emp
         WHERE deptno = 10) x;
--7.9计算模式
--出现最频繁的数据
SELECT MAX(sal) keep(dense_rank FIRST ORDER BY cnt DESC) sal
  FROM (SELECT sal, COUNT(1) cnt FROM hyz_emp WHERE deptno = 10 GROUP BY sal);
--7.10计算中间值
SELECT median(sal) FROM hyz_emp WHERE deptno = 20;
SELECT percentile_cont(0.5) within GROUP(ORDER BY sal)
  FROM hyz_emp
 WHERE deptno = 20;
SELECT sal FROM hyz_emp WHERE deptno = 20 ORDER BY sal;
--5 6258.00
--6 6628.00
SELECT (6258.00 + 6628.00) / 2 FROM dual;
--7.11求总和的百分比
SELECT (d10 / total) * 100 AS pct
  FROM (SELECT DISTINCT deptno,
                        SUM(sal) over() total,
                        SUM(sal) over(PARTITION BY deptno) d10
          FROM hyz_emp) x
 WHERE deptno = 10; --33.0741744459662
SELECT SUM(sal) total FROM hyz_emp s WHERE s.deptno = 10; --3332020
SELECT SUM(sal) total FROM hyz_emp s WHERE s.deptno = 20;
SELECT SUM(sal) total FROM hyz_emp s WHERE s.deptno = 30;
SELECT SUM(sal) total FROM hyz_emp s WHERE s.deptno = 40;
SELECT SUM(sal) total FROM hyz_emp s; --10074386
SELECT 3332020 / 10074386 * 100 FROM dual; --33.0741744459662
--7.12对可空列作聚集
--coalesce和nvl会忽略NULL值不计数
SELECT AVG(coalesce(comm, 0)) AS avg_comm FROM hyz_emp WHERE deptno = 30;--246.949579831933
SELECT AVG(nvl(comm, 0)) AS avg_comm FROM hyz_emp WHERE deptno = 30;--246.949579831933
SELECT AVG(comm) AS avg_comm FROM hyz_emp WHERE deptno = 30;--247.767539897621
--7.13计算不包含最大值和最小值的均值
SELECT AVG(sal)
  FROM (SELECT sal, MIN(sal) over() AS min_sal, MAX(sal) over() AS max_sal
          FROM hyz_emp) x
 WHERE sal NOT IN (min_sal, max_sal);
--7.14把数字字母串转为数值
SELECT regexp_substr('paull12332g14h334', '[0-9]+') AS s FROM dual;

本人是一枚程序猿,如果觉得整理的不错,请关注个人微信公众号(扫一扫):

猜你喜欢

转载自blog.csdn.net/huyingzuo/article/details/80117048