DM数据查询

DM数据查询笔记001


/*
HAVING 的作用和 WHERE 一样,都是起到过滤的作用,只不过 WHERE 是用于数据行,而 HAVING 则作用于分组
顺序不能乱:
SELECT ... FROM ... WHERE ... GROUP BY ... HAVING ... ORDER BY ...
子查询虽然是一种嵌套查询的形式,不过我们依然可以依据子查询是否执行多次,从而将子查询划分为关联子查询和非关联子查询
子查询从数据表中查询了数据结果,如果这个数据结果只执行一次,然后这个数据结果作为主查询的条件进行执行,那么这样的子查询叫做非关联子查询。
同样,如果子查询需要执行多次,即采用循环的方式,先从外部查询开始,每次都传入子查询进行查询,然后再将结果反馈给外部,这种嵌套的执行方式就称为关联子查询。
笛卡尔积也称为交叉连接,英文是 CROSS JOIN,它的作用就是可以把任意表进行连接,即使这两张表不相关

*/

/*使用 MERGE INTO 语法可合并 UPDATE 和 INSERT 语句。
通过 MERGE 语句,根据一张表(或视图)的连接条件对另外一张表(或视图)进行查询,
连接条件匹配上的进行 UPDATE(可能含有 DELETE),无法匹配的执行 INSERT。
*/


---单表查询
SELECT * FROM DMHR.CITY;

CREATE VIEW DMHR.TEM_VIEW AS SELECT * FROM DMHR.CITY;
SELECT * FROM DMHR.TEM_VIEW;

CREATE TABLE T1(ID INT,NAME CHAR,AGE INT);
INSERT INTO T1 VALUES(1,'H',10),(2,'J',12),(3,'K',13);
SELECT * FROM T1;

CREATE TABLE T2(ID INT,NAME CHAR);
INSERT INTO T2 VALUES(1,'H'),(2,'J'),(3,'K');
SELECT * FROM T2;

---为T2表添加列,列名是AGE,类型INT
ALTER TABLE T2 ADD AGE INT;

---使用MINUS/EXCEPT 查询T1中不同于T2的数据(表结构要相同)
SELECT * FROM T1 MINUS SELECT * FROM T2;  ---与下句等价
SELECT * FROM T1 EXCEPT SELECT * FROM T2;

---使用 INTERSECT 查询 T1表中和 T2表中都有的数据
SELECT * FROM T1 INTERSECT SELECT * FROM T2;

---谓词谓词包括比较谓词(=、>、<、>=、<=、<>), BETWEEN谓词、 IN谓词、LIKE谓词、NULL谓词、EXISTS谓词。

---(1)使用谓词比较查询
SELECT * FROM DMHR.DEPARTMENT;
SELECT * FROM DMHR.DEPARTMENT a 
WHERE a.DEPARTMENT_ID>=103 AND a.DEPARTMENT_ID<=202;

---(2)BETWEEN谓词
SELECT * FROM DMHR.DEPARTMENT a WHERE a.DEPARTMENT_ID BETWEEN 103 AND 202;
SELECT * FROM DMHR.DEPARTMENT a WHERE a.DEPARTMENT_ID not BETWEEN 103 AND 202;

---(3)IN谓词
---谓词IN可用来查询某列值属于指定集合的元组
SELECT * FROM DMHR.EMPLOYEE;
SELECT * FROM DMHR.EMPLOYEE a WHERE a.DEPARTMENT_ID IN(302,401);

--- (4)LIKE谓词
--- LIKE 谓词一般用来进行字符串的匹配 : <列名> LIKE <匹配字符串常数>
--- %代表任意字符串(也可以是空串); _代表任何一个字符。
---(%)和(_)的区别在于,(%)代表零个或多个字符,而(_)只代表一个字符。
SELECT * FROM DMHR.EMPLOYEE;
SELECT * FROM DMHR.EMPLOYEE a WHERE a.EMPLOYEE_NAME LIKE '%学%';
SELECT * FROM DMHR.EMPLOYEE a WHERE a.EMPLOYEE_NAME LIKE '_学_';

CREATE TABLE T3(ID INT,ADDRES CHAR);
ALTER TABLE SYSDBA.T3 MODIFY ADDRES VARCHAR(50);
INSERT INTO T3 VALUES(1,'123@ABC'),(2,'124@ABC'),(3,'125@ABC');
SELECT * FROM SYSDBA.T3;
SELECT * FROM SYSDBA.T3 WHERE T3.ADDRES LIKE '12_@%';

SELECT * FROM V$DM_INI a WHERE a.PARA_NAME LIKE 'SVR_%'; 

--- (5)NULL谓词
--- 0和空串是确定值  、NULL表示不确定的值
SELECT * FROM T3;
INSERT INTO T3(ID) VALUES(7);
SELECT * FROM SYSDBA.T3 WHERE T3.ADDRES IS NULL;
SELECT * FROM SYSDBA.T3 WHERE T3.ADDRES IS NOT NULL;

---逻辑谓词  AND, OR, NOT
SELECT * FROM DMHR.EMPLOYEE a WHERE a.DEPARTMENT_ID>102 AND a.DEPARTMENT_ID<106;


---集函数
---MAX MIN SUM AVG COUNT
SELECT * FROM DMHR.EMPLOYEE a WHERE a.DEPARTMENT_ID = 102;
SELECT MIN(EMPLOYEE_ID),MAX(EMPLOYEE_ID) FROM DMHR.EMPLOYEE a WHERE a.DEPARTMENT_ID = 102;

SELECT COUNT(*) FROM DMHR.DEPARTMENT;

---首行函数 FIRST_VALUE:返回查询项的首行记录
SELECT FIRST_VALUE(DEPARTMENT_NAME) FROM DMHR.DEPARTMENT;

---区间范围内的最大值函数 AREA_MAX
SELECT * FROM DMHR.EMPLOYEE;
SELECT AREA_MAX(SALARY,10000,20000) FROM DMHR.EMPLOYEE;

---DISTINCT 去重
SELECT DISTINCT(PARA_TYPE) FROM V$DM_INI;
SELECT PARA_NAME FROM V$DM_INI;

---分析函数 一般语法:分析函数名(参数) over 分析子句
---over()又称开窗函数  开窗函数包含三个子句:partition by(分组子句)、order by(排序)、rows(窗口子句)
---分析函数主要用于计算基于组(多行数据/窗口)的某种聚合值。
SELECT * FROM DMHR.EMPLOYEE;
---查工资大于25000的员工和最大工资
SELECT EMPLOYEE_NAME,MAX(SALARY) OVER(PARTITION BY EMPLOYEE_NAME) AS MAXSALARY
FROM DMHR.EMPLOYEE
WHERE SALARY>25000;

---查部门ID=302的员工名称和个数   !竟然没有重名的哈哈哈
SELECT EMPLOYEE_NAME,COUNT(*) OVER(PARTITION BY EMPLOYEE_ID) AS COUNT
FROM DMHR.EMPLOYEE
WHERE DEPARTMENT_ID=302;

---查部门302员工的名字以及薪资排名
---ROWS子句限定了计算范围
SELECT EMPLOYEE_NAME,MAX(SALARY) OVER(PARTITION BY DEPARTMENT_ID ORDER BY SALARY ROWS UNBOUNDED PRECEDING) AS RAAN_SALARY
FROM DMHR.EMPLOYEE
WHERE DEPARTMENT_ID=302;
SELECT EMPLOYEE_NAME,RANK() OVER(PARTITION BY DEPARTMENT_ID ORDER BY SALARY) AS RANK_SALARY
FROM DMHR.EMPLOYEE
WHERE DEPARTMENT_ID=302;

---情况表达式
---语法:SELECT ..,CASE WHEN.., THEN.., ELSE.., END(END AS..) FROM..
SELECT NAME,
CASE
WHEN (NAME = '中华书局' OR NAME = '清华大学出版社') AND CREDIT = 1 
THEN '采购'
ELSE '考虑'
END AS 选择
FROM PURCHASING.VENDOR;


--连接查询:查询包含的表个数>=2
--交叉连接(cross join)、自然连接(natural join)、内连接(inner)、外连接(outer)
/*
除了查询满足条件的记录以外,
外连接还可以查询某一方不满足条件的记录。
两张表的外连接,会有一张是主表,另一张是从表。
如果是多张表的外连接,那么第一张表是主表,即显示全部的行,而第剩下的表则显示对应连接的信息
*/
--无条件过滤
SELECT A.EMPLOYEE_NAME,B.DEPARTMENT_NAME 
FROM DMHR.EMPLOYEE A CROSS JOIN DMHR.DEPARTMENT B;
	
--条件过滤
SELECT * FROM DMHR.DEPARTMENT;
SELECT A.EMPLOYEE_NAME,B.DEPARTMENT_NAME 
FROM DMHR.EMPLOYEE A CROSS JOIN DMHR.DEPARTMENT B
WHERE B.DEPARTMENT_ID=201;

--交叉连接:
SELECT * FROM DMHR.EMPLOYEE;
SELECT * FROM DMHR.DEPARTMENT;

--自然连接:同名列作为连接条件  narure join、join.. using()
SELECT A.EMPLOYEE_NAME,B.DEPARTMENT_NAME 
FROM DMHR.EMPLOYEE A NATURAL JOIN DMHR.DEPARTMENT B; 
SELECT A.EMPLOYEE_NAME,B.DEPARTMENT_NAME 
FROM DMHR.EMPLOYEE A JOIN DMHR.DEPARTMENT B USING(DEPARTMENT_ID); 

/*
JOIN.. ON..
JOIN 关键字指定连接的两张表,
ON 子句指定连接条件表达式
*/
SELECT A.EMPLOYEE_NAME,B.DEPARTMENT_NAME 
FROM DMHR.EMPLOYEE A JOIN DMHR.DEPARTMENT B 
ON A.DEPARTMENT_ID = B.DEPARTMENT_ID AND A.DEPARTMENT_ID=101; 

--自连接 :数据库表与自身进行连接
--自身连接至少对一张表进行别名
SELECT A.EMPLOYEE_NAME,B.EMPLOYEE_NAME,A.EMPLOYEE_ID
FROM DMHR.EMPLOYEE A,DMHR.EMPLOYEE  B
WHERE A.EMPLOYEE_ID = B.EMPLOYEE_ID;

/*
内连接 INNER JOIN
结果集仅包含满足全部连接条件的记录
*/
SELECT A.EMPLOYEE_NAME,B.DEPARTMENT_NAME
FROM DMHR.EMPLOYEE A INNER JOIN DMHR.DEPARTMENT B
ON A.DEPARTMENT_ID = B.DEPARTMENT_ID;

/*
外连接:外连接对结果集进行了扩展,会返回一张表的所有记录,对于另一张表无法匹配的字段用 NULL 填充返回。
左外连接:返回左表所有记录
右外连接:返回右表所有记录
全外连接:返回两张表的全部记录
*/
SELECT A.EMPLOYEE_NAME,B.DEPARTMENT_NAME
FROM DMHR.EMPLOYEE A RIGHT JOIN DMHR.DEPARTMENT B
ON A.DEPARTMENT_ID = B.DEPARTMENT_ID;

/*
子查询:查询块嵌套查询块的查询
一个查询块:
SELECT.. FROM.. WHERE..

嵌套查询:
比如:SELECT.. FROM.. WHERE.. IN (SELECT.. FROM.. WHERE.. );
*/
SELECT 'VALUE IS', LEFT((SELECT ADDRESS1 FROM PERSON. ADDRESS WHERE ADDRESSID= 1), 8) 
FROM PERSON.ADDRESS_TYPE;

SELECT ORDERDATE, STATUS, TOTAL
FROM PURCHASING.PURCHASEORDER_HEADER
WHERE (EMPLOYEEID, VENDORID) IN
(SELECT T1.EMPLOYEEID, T2.VENDORID
FROM RESOURCES.EMPLOYEE T1, PURCHASING.VENDOR T2
WHERE T1.TITLE = '采购代表' AND T2.NAME = '清华大学出版社');

--标量子查询:子查询(嵌套进去)应该返回一行一列,否则报错
--正确1:
SELECT 'VALUE IS', 
(SELECT ADDRESS1 FROM PERSON.ADDRESS WHERE ADDRESSID = 1)
FROM PERSON.ADDRESS_TYPE;
--正确2:
SELECT 'VALUE IS', 
LEFT((SELECT ADDRESS1 FROM PERSON. ADDRESS WHERE ADDRESSID= 1), 8)
FROM PERSON.ADDRESS_TYPE;
--错误1:SELECT语句列数超长(子查询返回的列数不止1)
SELECT 'VALUE IS', 
(SELECT ADDRESS1, CITY FROM PERSON.ADDRESS WHERE ADDRESSID = 1) 
FROM PERSON.ADDRESS_TYPE;
--错误2:-4097: 单行子查询返回多行(子查询返回的行数不止1)
SELECT 'VALUES IS', 
(SELECT ADDRESS1 FROM PERSON.ADDRESS)
FROM PERSON.ADDRESS_TYPE;

--表子查询
/*
注意:
当确定子查询结果只有一个元组(记录)时,才可以使用‘=’,否则只能用IN谓词(即查询结果多个元组)
*/
SELECT EMPLOYEEID, SALESTHISYEAR, SALESLASTYEAR
FROM SALES.SALESPERSON
WHERE EMPLOYEEID IN
( SELECT EMPLOYEEID
FROM RESOURCES.EMPLOYEE
WHERE TITLE = '销售代表'
);

--例:查询对目录名为小说的图书进行评论的人员名称和评论日期。
SELECT DISTINCT NAME, REVIEWDATE
FROM PRODUCTION.PRODUCT_REVIEW
WHERE PRODUCTID IN
( SELECT PRODUCTID
FROM PRODUCTION.PRODUCT
WHERE PRODUCT_SUBCATEGORYID IN
( SELECT PRODUCT_SUBCATEGORYID
FROM PRODUCTION.PRODUCT_SUBCATEGORY
WHERE PRODUCT_CATEGORYID IN
( SELECT PRODUCT_CATEGORYID
FROM PRODUCTION.PRODUCT_CATEGORY
WHERE NAME = '小说'
)
)
);
/*解说:
该语句采用了四层嵌套查询方式,
首先通过最内层子查询从 PRODUCT_CATEGORY 中查出目录名为小说的目录编号,
然后从 PRODUCT_SUBCATEGORY 中查出这些目录编号对应的子目录编号,
接着从 PRODUCT 表中查出这些子目录编号对应的图书的编号,
最后由最外层查询查出这些图书编号对应的评论人员和评论日期。
*/


--查询每个目录的编号、名称和对应的子目录的数量,并按数量递减排列。
SELECT T1.PRODUCT_CATEGORYID, T1.NAME, T2.NUM
FROM PRODUCTION.PRODUCT_CATEGORY T1,
( SELECT PRODUCT_CATEGORYID, COUNT(PRODUCT_SUBCATEGORYID)
FROM PRODUCTION.PRODUCT_SUBCATEGORY
GROUP BY PRODUCT_CATEGORYID
) AS T2(PRODUCT_CATEGORYID,NUM)
WHERE T1.PRODUCT_CATEGORYID = T2.PRODUCT_CATEGORYID
ORDER BY T2.NUM DESC;

/*解读:
首先根据目录编号分组返回每种目录的编号和对应子目录的数量,并虚拟为表T2的列
然后通过连接条件讲对应的目录的子目录数量返回,同时按数量递减排列
*/


--定量比较 All Some Any




/*
with子句
临时声明并定义存储函数,偶尔需要存储过程
和公用表表达式 CTE 类似, WITH FUNCTION 定义的存储函数对象也不会存储到系统表中,且只在当前 SQL 语句内有效

WITH子句: WITH FUNCTION/WITH CTE
公用表表达式(CTE)是一个在查询中定义的临时命名结果集,将在 FROM 子句中使用它 

相比模式对象中的存储函数,通过 WITH FUNCTION 定义的存储函数在对象名解析时拥有更高的优先级。

*/
WITH FUNCTION f1(C INT) RETURN INT AS BEGIN RETURN C * 10; END;
SELECT f1(5236) FROM DUAL;
/

SELECT * FROM DUAL;

/*
GROUP BY子句逻辑地将由 WHERE 子句返回的临时结果重新编组。结果是行的集合,一组内一个分组列的所有值都是相同的。 
HAVING子句用于为组设置检索条件

*/
--统计每个部门的员工数
SELECT DEPARTMENT_ID,COUNT(*) 
FROM DMHR.EMPLOYEE A
GROUP BY DEPARTMENT_ID
ORDER BY COUNT(*);



/*
视图作为一张虚拟表,帮我们封装了底层与数据表的接口。它相当于是一张表或多张表的数据结果集。

CREATE VIEW view_name AS
SELECT column1, column2
FROM table
WHERE condition
当视图创建之后,它就相当于一个虚拟表,可以直接使用

临时表和视图的区别:
视图是虚拟表,本身不存储数据,如果想要通过视图对底层数据表的数据进行修改也会受到很多限制,
通常我们是把视图用于查询,也就是对 SQL 查询的一种封装。
临时表是真实存在的数据表,不过它不用于长期存放数据,只为当前连接存在,关闭连接后,临时表就会自动释放。
在实际工作中,我们可能会见到各种临时数据。
比如你做一个电商的系统,中间会有个购物车的功能,需要临时统计购物车中的商品和金额,那该怎么办呢?
这里就需要用到临时表了,
*/

/*
存储过程

CREATE PROCEDURE 存储过程名称([参数列表])
BEGIN
    需要执行的语句
END    


CREATE PROCEDURE add_num(n IN OUT INT)
BEGIN
       DECLARE i INT;
       DECLARE sum INT;
       
       SET i = 1;
       SET sum = 0;
       WHILE i <= n DO
              SET sum = sum + i;
              SET i = i +1;
       END WHILE;
       SELECT sum;
END;

*/

/*
行式存储是把一行的数据都串起来进行存储,然后再存储下一行。
同样,列式存储是把一列的数据都串起来进行存储,然后再存储下一列。
这样做的话,相邻数据的数据类型都是一样的,更容易压缩,压缩之后就自然降低了 I/O。
*/

EXPLAIN SELECT * FROM DMHR.EMPLOYEE WHERE EMPLOYEE.DEPARTMENT_ID=1102;
SELECT * FROM DMHR.EMPLOYEE WHERE EMPLOYEE.DEPARTMENT_ID=1102;

--事务管理
--设置保存点
SAVEPOINT T1; --新建保存点

CREATE TABLE T7(ID INT);
INSERT INTO T7 VALUES(1),(2),(3);
SAVEPOINT T2;
INSERT INTO T7 VALUES(4),(5),(6);
SELECT * FROM T7;
ROLLBACK TO SAVEPOINT T1; --回滚到保存点T2
COMMIT;

--测试保存点是否在事务提交之后生效
CREATE TABLE T8(ID INT);
SAVEPOINT T1;
INSERT INTO T8 VALUES(1),(2),(3);
SELECT * FROM T8;
SAVEPOINT T2;
INSERT INTO T8 VALUES(4),(5),(6);
SELECT * FROM T8;
ROLLBACK TO SAVEPOINT T2;
COMMIT;
ROLLBACK TO SAVEPOINT T2; --事务提交之后就不能再进行回滚保存点操作


--隔离级别:读未提交、读提交、不可重复、可序列化
--例:设置读提交隔离
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
SELECT * FROM SYS."V$RLOG";

--支持闪回:闪回功能的设计为了以防万一的操作失误
--ENABLE_FLASHBACK=1为开启闪回功能
--DM MPP、 DMDSC 和 DMDPC 环境不支持闪回查询。
--闪回管理语句
SELECT * FROM V$DM_INI WHERE "V$DM_INI".PARA_NAME LIKE 'ENABLE_FLASHBACK';
SELECT * FROM V$FLASHBACK_TRX_INFO;

--- 测试SQL优化(极客时间内容)
---索引
SELECT * FROM DMHR.EMPLOYEE;
CREATE INDEX N1 ON DMHR.EMPLOYEE(EMPLOYEE_NAME);

UPDATE DMHR.EMPLOYEE
SET EMPLOYEE_NAME = 'CHENQIANG' 
WHERE EMPLOYEE_ID = 9001;

DROP INDEX DMHR.N1;

UPDATE DMHR.EMPLOYEE
SET EMAIL = '[email protected]' 
WHERE EMPLOYEE_NAME='马起芬';

CREATE INDEX T1 ON DMHR.EMPLOYEE(EMPLOYEE_NAME);


--数据库优化
--数据库会话监控
--查询活动会话数
select count(*) from v$sessions where state='ACTIVE';
--已执行超过2秒的活动SQL
/*
DATEDIFF(datepart,date1,date2)返回跨两个指定日期的日期和时间边界数
*/
select * from (
SELECT sess_id,sql_text,datediff(ss,last_send_time,sysdate) Y_EXETIME,
       SF_GET_SESSION_SQL(SESS_ID) fullsql,clnt_ip
 FROM V$SESSIONS WHERE STATE='ACTIVE')
 where Y_EXETIME>=2;

--锁查询
select o.name,l.* 
from v$lock l,sysobjects o 
where l.table_id=o.id and blocked=1


--已执行超过2秒的活动SQL
SELECT * from (
SELECT sess_id,sql_text,datediff(ss,last_send_time,sysdate) Y_EXETIME,
       SF_GET_SESSION_SQL(SESS_ID) fullsql,clnt_ip
 FROM V$SESSIONS WHERE STATE='ACTIVE')
 where Y_EXETIME>=2;

select * from SYS."V$SESSIONS" where SESS_ID = 17912128;


SELECT * FROM SYS."V$SQL_HISTORY";

SELECT * FROM V$SESSIONS WHERE STATE = 'IDLE';

SELECT * FROM V$SESSIONS;

--
SELECT DATEDIFF(SS,LAST_RECV_TIME,SYSDATE) SS,
DBMS_LOB.SUBSTR(SF_GET_SESSION_SQL(SESS_ID)), * 
FROM V$SESSIONS WHERE STATE = 'ACTIVE'
ORDER BY SS DESC;

SELECT * FROM V$LONG_EXEC_SQLS;
SELECT * FROM v$dmsql_exec_time where EXEC_ID = ?;

待见。。

你可能感兴趣的:(DM,数据库,sql,DM)