ORACLE学习之WITH...AS用法

--比如我想通过一段sql查询当前用户下所有的表信息,如数据量大小,统计分析,其表的字段,及其说明
--我们用两种方法来满足需求
--1.平时我们实现此步骤会使用join操作实现:
SELECT rownum AS max_size,
       s.table_name,
       s.last_analyzed,
       s.num_rows,
       o.column_name,
       o.column_name
  FROM user_tables s
  JOIN user_col_comments o
    ON s.table_name = o.table_name
 WHERE s.num_rows >= 1000
   AND s.table_name LIKE 'HYZ%';
--2.使用with...as实现
WITH usertable AS --定义名称时不要和表名相同
 (SELECT s.table_name, s.last_analyzed, s.num_rows FROM user_tables s),
usercolcomments AS --定义名称时不要和表名相同
 (SELECT o.table_name, o.column_name, o.comments FROM user_col_comments o)
SELECT rownum AS max_size,
       s.table_name,
       s.last_analyzed,
       s.num_rows,
       o.column_name,
       o.column_name
  FROM usertable s
  JOIN usercolcomments o
    ON s.table_name = o.table_name
 WHERE s.num_rows >= 1000
   AND s.table_name LIKE 'HYZ%';
--此两种实现方式都实现了同样的需求,以上需求并看不出with..as的优势,如果我们增加如下需求
--查询表空间的相关详情数据
SELECT a.tablespace_name AS 表空间名,
       SUM(a.bytes) AS "总空间(B)",
       SUM(b.bytes) AS "已使用(B)",
       SUM(c.bytes) AS "剩余空间(B)",
       SUM((b.bytes * 100) / a.bytes) "已使用比例(%)",
       SUM((c.bytes * 100) / a.bytes) "空闲比例(%) ",
       (SUM(c.bytes) / 1024 / 1024 / 1024) AS "剩余空间(GB)"
  FROM sys.sm$ts_avail a, sys.sm$ts_used b, sys.sm$ts_free c
 WHERE a.tablespace_name = b.tablespace_name
   AND a.tablespace_name = c.tablespace_name
 GROUP BY a.tablespace_name
 ORDER BY a.tablespace_name;
--此时我们使用join的时候发现把此表放进去以后
SELECT rownum AS max_size,
       s.table_name,
       s.last_analyzed,
       s.num_rows,
       o.column_name,
       o.column_name,
       k.表空间名,
       k."总空间(B)",
       k."已使用(B)",
       k."剩余空间(B)",
       k."已使用比例(%)",
       k."空闲比例(%) ",
       k."剩余空间(GB)"
  FROM user_tables s
  JOIN user_col_comments o
    ON s.table_name = o.table_name
  JOIN (SELECT a.tablespace_name AS 表空间名,
               SUM(a.bytes) AS "总空间(B)",
               SUM(b.bytes) AS "已使用(B)",
               SUM(c.bytes) AS "剩余空间(B)",
               SUM((b.bytes * 100) / a.bytes) "已使用比例(%)",
               SUM((c.bytes * 100) / a.bytes) "空闲比例(%) ",
               (SUM(c.bytes) / 1024 / 1024 / 1024) AS "剩余空间(GB)"
          FROM sys.sm$ts_avail a, sys.sm$ts_used b, sys.sm$ts_free c
         WHERE a.tablespace_name = b.tablespace_name
           AND a.tablespace_name = c.tablespace_name
         GROUP BY a.tablespace_name
         ORDER BY a.tablespace_name) k
    ON k.表空间名 = s.tablespace_name
 WHERE s.num_rows >= 1000
   AND s.table_name LIKE 'HYZ%';
--无论是美观还是后期如果新增复杂的sql使用join或left join连接都十分的不方便,如果稍有报错还得仔细查看   
--如果我们使用with...as
WITH usertable AS --定义名称时不要和表名相同
 (SELECT s.table_name, s.last_analyzed, s.num_rows, s.tablespace_name
    FROM user_tables s),
usercolcomments AS --定义名称时不要和表名相同
 (SELECT o.table_name, o.column_name, o.comments FROM user_col_comments o),
tablespaces AS
 (SELECT a.tablespace_name AS 表空间名,
         SUM(a.bytes) AS "总空间(B)",
         SUM(b.bytes) AS "已使用(B)",
         SUM(c.bytes) AS "剩余空间(B)",
         SUM((b.bytes * 100) / a.bytes) "已使用比例(%)",
         SUM((c.bytes * 100) / a.bytes) "空闲比例(%) ",
         (SUM(c.bytes) / 1024 / 1024 / 1024) AS "剩余空间(GB)"
    FROM sys.sm$ts_avail a, sys.sm$ts_used b, sys.sm$ts_free c
   WHERE a.tablespace_name = b.tablespace_name
     AND a.tablespace_name = c.tablespace_name
   GROUP BY a.tablespace_name
   ORDER BY a.tablespace_name)
SELECT rownum AS max_size,
       s.table_name,
       s.last_analyzed,
       s.num_rows,
       o.column_name,
       o.column_name,
       k.表空间名,
       k."总空间(B)",
       k."已使用(B)",
       k."剩余空间(B)",
       k."已使用比例(%)",
       k."空闲比例(%) ",
       k."剩余空间(GB)"
  FROM usertable s
  JOIN usercolcomments o
    ON s.table_name = o.table_name
  JOIN tablespaces k
    ON k.表空间名 = s.tablespace_name
 WHERE s.num_rows >= 1000
   AND s.table_name LIKE 'HYZ%';
--此时我们只需要保证usertable,usercolcomments,tablespaces括号内逻辑无问题,使用时字段补全
--既能保证美观,又能对复杂的sql进行临时查询,有时候我们会采用临时表去处理此类,方便取数和分析问题
--但是如果使用with...as对我们的工作和需求是事半功倍的
--重要的是再复杂的逻辑我们并不需要建实际的临时表,避免了如果稍有逻辑的问题,又得重新建临时表
--我们可以尝试把所有逻辑或运算进行如下处理
WITH usertable AS --定义名称时不要和表名相同  
 (SELECT s.table_name, s.last_analyzed, s.num_rows, s.tablespace_name
    FROM user_tables s),
usercolcomments AS --定义名称时不要和表名相同  
 (SELECT o.table_name, o.column_name, o.comments FROM user_col_comments o),
tablespaces AS
 (SELECT a.tablespace_name AS tablespace_name,
         SUM(a.bytes) AS total_space,
         SUM(b.bytes) AS used_space,
         SUM(c.bytes) AS remaining_space,
         SUM((b.bytes) / a.bytes) AS used_space_bl,
         SUM((c.bytes) / a.bytes) remaining_space_bl,
         (SUM(c.bytes)) AS remaining_space_gb
    FROM sys.sm$ts_avail a, sys.sm$ts_used b, sys.sm$ts_free c
   WHERE a.tablespace_name = b.tablespace_name
     AND a.tablespace_name = c.tablespace_name
   GROUP BY a.tablespace_name
   ORDER BY a.tablespace_name)
--把所有的复杂的运算放到以下sql处理,使得上面的在复杂的逻辑也能保持整个sql的美观  
SELECT rownum AS max_size,
       s.table_name,
       s.last_analyzed,
       s.num_rows,
       o.column_name,
       o.column_name,
       k.tablespace_name,
       k.total_space AS "总空间(B)",
       k.used_space AS "已使用(B)",
       k.remaining_space AS "剩余空间(B)",
       k.used_space_bl * 100 AS "已使用比例(%)",
       k.remaining_space_bl * 100 AS "空闲比例(%) ",
       k.remaining_space_gb / 1024 / 1024 / 1024 AS "剩余空间(GB)"
  FROM usertable s
  JOIN usercolcomments o
    ON s.table_name = o.table_name
  JOIN tablespaces k
    ON k.tablespace_name = s.tablespace_name
 WHERE s.num_rows >= 1000
   AND s.table_name LIKE 'HYZ%';

你可能感兴趣的:(ORACLE)