几个行列转换的实用小例子(r4笔记第2天)

时间:2022-05-04
本文章向大家介绍几个行列转换的实用小例子(r4笔记第2天),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

起行列转换,大家是既熟悉又陌生,在oracle 10g版本之前如果要做行列转换,都基本得使用decode来完成,在11g中情况有了改观,可以直接使用pivot特性来完成。这种方式相比decode来说要更加简洁清晰。 我们来举两个例子来说明一下。 -->session状态的监控 对于数据库中的session状态监控可以作为系统运维工作的一部分,一旦发现session异常就可以很快定位出可能是哪些类型的问题。 我们创建一个临时表来替代v$session来说明。 create table session_test as select *from v$session;

select username,count(*)cnt,status from session_test group by username,status;

我们得到的当前session情况如下: USERNAME CNT STATUS ------------------------------ ---------- -------- N1 1 ACTIVE MIG 1 INACTIVE 25 ACTIVE 如果用户很多,同一个用户下存在多个session(ACTIVE或者INACTIVE)。 查看的时候就不是很清晰。如果能够行列转换一下,显示成下面的格式就好了。 username active inactive sniped..... xxxx 1 2 0 xxxx 2 0 0 可以使用pivot来实现。

select *from  
(
select username,status from session_test 
)
pivot
(
count(status)
for status in  ('ACTIVE','INACTIVE','KILLED','SNIPED','CACHED')
)
order by username nulls  first;

输出结果如下:

USERNAME 'ACTIVE' 'INACTIVE' 'KILLED' 'SNIPED' 'CACHED' ------------------------------ ---------- ---------- ---------- ---------- ---------- 25 0 0 0 0 MIG 0 1 0 0 0 N1 1 0 0 0 0 这种方式相比以前的decode方式要好很多,而且要清晰。不过有一点,这种方式中,for status in ('ACTIVE','INACTIVE','KILLED','SNIPED','CACHED')的部分是需要预先知道的。在这个例子中不是问题,因为状态很有限,就那几个,可以通过官方文档中的v$session字段解释得到。session的状态就下面5种。

STATUS

VARCHAR2(8)

Status of the session:ACTIVE - Session currently executing SQLINACTIVEKILLED - Session marked to be killedCACHED - Session temporarily cached for use by Oracle*XASNIPED - Session inactive, waiting on the client

  • ACTIVE - Session currently executing SQL
  • INACTIVE
  • KILLED - Session marked to be killed
  • CACHED - Session temporarily cached for use by Oracle*XA
  • SNIPED - Session inactive, waiting on the client

-->查看schema下的object_type 如果我们查看一个数据库中数据的整体分布情况,想知道每个schema下的object分布情况,比如存在多少个表,多少索引,同义词等,这些对于很多潜在的问题分析都是很有帮助的。如果同样结构的环境中丢失了某一个同义词,可能需要很长的时间才能发现问题,如果我们简单比较一下object的分布情况,就可以很容易的分析出问题来。 我们采用all_objects做为数据来源,创建一个临时表来处理。

create table obj_test as select *from all_objects;
select owner,object_type,count(*) from obj_test group by  owner,object_type order by owner;

得到的结果如下:

SCOTT                          TABLE                         5
SYS                            CLUSTER                      10
SYS                            CONSUMER GROUP                2
SYS                            CONTEXT                       3
SYS                            DESTINATION                   2
SYS                            DIRECTORY                    10
SYS                            EDITION                       1
SYS                            EVALUATION CONTEXT          10
OWNER                          OBJECT_TYPE            COUNT(*)
------------------------------ -------------------  ----------
SYS                            FUNCTION                     87
SYS                            INDEX                      1018
SYS                            INDEX PARTITION             121
SYS                            JOB                           9
SYS                            JOB CLASS                    13
SYS                            LIBRARY                     142
SYS                            OPERATOR                      7
SYS                            PACKAGE                     579
SYS                            PACKAGE BODY                556
SYS                            PROCEDURE                    93
SYS                            PROGRAM                      19
SYS                            RULE                          1
SYS                            RULE SET                     13
SYS                            SCHEDULE                      3
SYS                            SCHEDULER GROUP               4
SYS                            SEQUENCE                    116
SYS                            SYNONYM                       6
SYS                            TABLE                       989
SYS                            TABLE PARTITION             121
SYS                            TABLE SUBPARTITION           32
SYS                            TRIGGER                      4

可以很清楚地看到每个用户下的object的分布情况,但是这样看很不清晰,而且我们可能并不需要知道所有的object_type,我们只是想得到一些基本的object type的情况。 可以采用如下的方式来做。

select *from 
(
select owner,object_type from  obj_test 
)
pivot
(
count(*)
for object_type in  ('TABLE','INDEX','SYNONYM','PROCEDURE','FUNCTION','PACKAGE','VIEW')
)
order  by owner;
OWNER                             'TABLE'    'INDEX'  'SYNONYM'  'PROCEDURE' 'FUNCTION'  'PACKAGE'     'VIEW'
------------------------------  ---------- ---------- ---------- ----------- ---------- ----------  ----------
APPQOSSYS                               4          0           1           0          0          0           0
APP_CONN                                0          0          4            0          0          0          0
DBSNMP                                  20         10          1           1          0          3           7
JEANRON                                 1          0          0            0          0          0          0
MIG                                      0          0          1           0          0          0           0
N1                                     46         10          0            5          3          3          0
ORACLE_OCM                               0          0          0           0          0          3           0
OUTLN                                   3          4          0            1          0          0          0
PUBLIC                                   0          0       3281           0          0          0           0
SCOTT                                   5          2          0            0          0          0          0
SYS                                    989       1018          6          93         87        579        3730
SYSTEM                                157        215           8           1          0          1          14
TABOWNER                                1          0          0            0          0          0           0

上面这种方式要清晰地多,而且更有针对性。 当然关于行列转换,model子句也是很实用的,准备在后续的博客中继续分享。我们抛砖引玉,用一个在论坛中比较有意思的例子来说明一下。 大家能够猜出下面的sql语句运行的结果吗?稍微停顿一下再看答案。

select  c from
(select * from
(select 'oracle' cc, level no from dual connect by  level <= length('oracle'))
model return updated rows
dimension by  (no)
measures (cc c, no n)
rules (
   c[any] =  substr(c[cv()],n[cv()],1)
));



C
------
o
r
a
c
l
e
6 rows selected.