WITH konstrukcijas izmantošanas varianti The WITH query_name clause lets you assign a name to a subquery block. You can then reference the subquery block multiple places in the query by specifying query_name. Oracle Database optimizes the query by treating the query name as either an inline view or as a temporary table. WITH <alias_one> as (subquery_sql_statement), <alias_two> as (sql_statement_from_alias_one) SELECT <column_name_list> FROM <alias_one>, <alias_two> WHERE <join_condition>; WITH Q1 as (SELECT dummy FROM DUAL) SELECT dummy FROM Q1; WITH Q1 AS (SELECT inst_id FROM gv$session), Q2 AS (SELECT unique inst_id FROM Q1 UNION ALL SELECT unique inst_id FROM Q1) 1
30
Embed
datubaze.files.wordpress.com viewWITH konstrukcijas izmantošanas varianti. The . WITH. query_name. clause lets you assign a name to a subquery block. You can then reference the subquery
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
WITH konstrukcijas izmantošanas varianti
The WITH query_name clause lets you assign a name to a subquery block.
You can then reference the subquery block multiple places in the query by specifying query_name. Oracle Database optimizes the query by treating the query name as either an inline view or as a temporary table.
WITH <alias_one> as (subquery_sql_statement), <alias_two> as (sql_statement_from_alias_one)
The column aliases following the query_name and the set operators separating multiple subqueries in the AS clause are valid and required for recursive subquery factoring.
The search_clause and cycle_clause are valid only for recursive subquery factoring but are not required.
You can specify this clause in any top-level SELECT statement and in most types of subqueries. The query name is visible to the main query and to all subsequent subqueries. For recursive subquery factoring, the query name is even visible to the subquery that defines the query name itself.
4
Recursive Subquery Factoring If a subquery_factoring_clause refers to its own query_name in the subquery that defines it, then the subquery_factoring_clause is said to be recursive. A recursive subquery_factoring_clause must contain two query blocks:
1) the first is the anchor member. The anchor member must appear before the recursive member, and it cannot reference query_name. The anchor member can be composed of one or more query blocks combined by the set operators: UNION ALL, UNION, INTERSECT or MINUS.
2) the second is the recursive member. The recursive member must follow the anchor member and must reference query_name exactly once. You must combine the recursive member with the anchor member using the UNION ALL set operator.
The number of column aliases following WITH query_name and the number of columns in the SELECT lists of the anchor and recursive query blocks must be the same.
5
search_clause Use the SEARCH clause to specify an ordering for the rows.1. Specify BREADTH FIRST BY if you want sibling rows returned before any child rows are returned.2. Specify DEPTH FIRST BY if you want child rows returned before any siblings rows are returned.3. Sibling rows are ordered by the columns listed after the BY keyword.4. The c_alias list following the SEARCH keyword must contain column names from the column alias list for query_name.5. The ordering_column is automatically added to the column list for the query name. The query that selects from query_name can include an ORDER BY on ordering_column to return the rows in the order that was specified by the SEARCH clause.
6
cycle_clause
Use the CYCLE clause to mark cycles in the recursion.1. The c_alias list following the CYCLE keyword must contain column names from the column alias list for query_name. Oracle Database uses these columns to detect a cycle.2. cycle_value and no_cycle_value should be character strings of length 1.3. If a cycle is detected, then the cycle mark column specified by cycle_mark_c_alias for the row causing the cycle is set to the value specified for cycle_value. The recursion will then stop for this row. That is, it will not look for child rows for the offending row, but it will continue for other noncyclic rows.4. If no cycles are found, then the cycle mark column is set to the default value specified for no_cycle_value.5. The cycle mark column is automatically added to the column list for the query_name.6. A row is considered to form a cycle if one of its ancestor rows has the same values for the cycle columns.If you omit the CYCLE clause, then the recursive WITH clause returns an error if cycles are discovered. In this case, a row forms a cycle if one of its ancestor rows has the same values for all the columns in the column alias list for query_name that are referenced in the WHERE clause of the recursive member.
7
Subquery factoring example
The following statement creates the query names dept_costs and avg_cost for the initial query block containing a join, and then uses the query names in the body of the main query.
WITH dept_costs AS ( SELECT department_name, SUM(salary) dept_total FROM employees e, departments d WHERE e.department_id = d.department_id GROUP BY department_name), avg_cost AS ( SELECT SUM(dept_total)/COUNT(*) avg FROM dept_costs)
SELECT * FROM dept_costs WHERE dept_total > (SELECT avg FROM avg_cost) ORDER BY department_name;
Department total salaries>average of all Departments total salaries
8
Departamentu darbinieku algu summa un vidējā visu departamentu darbinieku algu summa
select 'AVG ', 0 DE_KOPĀ, AVG(c.DE_KOPĀ)from (select b.DE_NOS, SUM(a.ALGA) DE_KOPĀ from DARBINIEKI a, DEPARTAMENTI b where a.DE_NUM = b.DE_NUM group by b.DE_NOS) cUNION ALLselect e.DE_NOS, SUM(d.ALGA) DE_KOPĀ, 0 from DARBINIEKI d, DEPARTAMENTI e where d.DE_NUM = e.DE_NUM group by e.DE_NOS;
9
Pakārtotais vaicājums ar starpniecību (subquery factoring statement)
WITH DE_IZMAKSAS as ( select DE_NOS, SUM(ALGA) DE_KOPĀ from DARBINIEKI a, DEPARTAMENTI b where a.DE_NUM = b.DE_NUM group by DE_NOS), VID_IZMAKSAS as ( select SUM(DE_KOPĀ)/COUNT(*) VID from DE_IZMAKSAS)
select * from DE_IZMAKSASwhere DE_KOPĀ>= (select VID from VID_IZMAKSAS) order by DE_NOS;
Departamenta nosaukums un darbinieku algu summa.
Vidējā departamentu darbinieku algu summa.
Departamenti, kuru darbinieku algu summa ir lielāka vai vienāda ar vidējo departamentu darbinieku algu summu
10
Recursive subquery factoring
Examples The following statement shows the employees who directly or indirectly report to employee 101 and their reporting level.
WITH reports_to_101 (eid, emp_last, mgr_id, reportLevel) AS ( SELECT employee_id, last_name, manager_id, 0 reportLevel FROM employees WHERE employee_id = 101 UNION ALL SELECT e.employee_id, e.last_name, e.manager_id, reportLevel+1 FROM reports_to_101 r, employees e WHERE r.eid = e.manager_id )
SELECT eid, emp_last, mgr_id, reportLevelFROM reports_to_101ORDER BY reportLevel, eid;
Noteikt darbiniekus, kuri tieši vai netieši sniedz pārskatus 1 darbiniekam un viņu atskaišu līmeni.
Darbinieku pakārtotības koks
1 DEP_1
2 DEP_1 3 DEP_1
4 DEP_1 5 DEP_1
6 DEP_2 10 DEP_3
9 DEP_2
8 DEP_27 DEP_2
12 DEP_3
11 DEP_3
12
Tabulu izveidošana
create table DARBINIEKI(DA_NUM number Primary key,DA_UZV varchar2(20),ALGA number(8,2),DE_NUM number,VADIT_NU number);
insert into DARBINIEKI values(1, 'Sakne', 900,1,NULL);insert into DARBINIEKI values(2, 'Zars', 800,1,1);insert into DARBINIEKI values(3, 'Stumrs', 800,1,1);insert into DARBINIEKI values(4, 'Sakne', 600,1,2);insert into DARBINIEKI values(5, 'Lapa', 600,1,2);insert into DARBINIEKI values(6, 'Ozols', 800,2,1);insert into DARBINIEKI values(7, 'Osis', 700,2,6);insert into DARBINIEKI values(8, 'Alksnis', 700,2,6);insert into DARBINIEKI values(9, 'Egle', 700,2,8);insert into DARBINIEKI values(10, 'Priede', 800,3,1);insert into DARBINIEKI values(11, 'Virsis', 700,3,10);insert into DARBINIEKI values(12, 'Persiks', 600,3,11);
create table DEPARTAMENTI(DE_NUM number Primary key,DE_NOS varchar2(20));
insert into DEPARTAMENTI values(1, 'DEP1');insert into DEPARTAMENTI values(2, 'DEP2');insert into DEPARTAMENTI values(3, 'DEP3');
13
WITH ATSK_1 (NUM, UZV, VADIT, ATS_LIM) AS (select DA_NUM, DA_UZV, VADIT_NU, 0 ATS_LIM from DARBINIEKI where DA_NUM = 1 UNION ALL select e.DA_NUM, e.DA_UZV, e.VADIT_NU, ATS_LIM+1 from ATSK_1 r, DARBINIEKI e where r.NUM = e.VADIT_NU )
select NUM, UZV, VADIT, ATS_LIMfrom ATSK_1order by ATS_LIM, NUM;
14
Noteikt darbiniekus, kuri tieši vai netieši sniedz pārskatus 1 darbiniekam, viņu atskaišu līmeni un vadītāju ķēdi.
with ATSK_1 (NUM, UZV, VADIT, ATS_LIM, VAD_SAR) AS (select DA_NUM, DA_UZV, VADIT_NU, 0 ATS_LIM, CAST(VADIT_NU as varchar2(200)) from DARBINIEKI where DA_NUM= 1 UNION ALL select e.DA_NUM, e.DA_UZV, e.VADIT_NU, ATS_LIM+1, CAST(VAD_SAR || ',' || VADIT_NU as varchar2(200)) FROM ATSK_1 r, DARBINIEKI e WHERE r.NUM = e.VADIT_NU )
select NUM, UZV, VADIT, ATS_LIM, VAD_SARfrom ATSK_1order by ATS_LIM, NUM;
15
Noteikt darbiniekus, kuri tieši vai netieši sniedz pārskatus 1 darbiniekam un atrodas tiešā pakļautībā (1 līmenis)
with ATSK_1 (NUM, UZV, VADIT, ATS_LIM, VAD_SAR) AS (select DA_NUM, DA_UZV, VADIT_NU, 0 ATS_LIM, CAST(VADIT_NU as varchar2(200)) from DARBINIEKI where DA_NUM= 1 UNION ALL select e.DA_NUM, e.DA_UZV, e.VADIT_NU, ATS_LIM+1, CAST(VAD_SAR || ',' || VADIT_NU as varchar2(200)) FROM ATSK_1 r, DARBINIEKI e WHERE r.NUM = e.VADIT_NU )select NUM, UZV, VADIT, ATS_LIM, VAD_SARfrom ATSK_1where ATS_LIM <=1order by ATS_LIM, NUM;
16
Grafiska pakārtotības shemas izvade
with POZ_IZV (NUM, UZV, VADIT, ATS_LIM, ALGA) as (select DA_NUM, DA_UZV, VADIT_NU, 0 ATS_LIM, ALGA from DARBINIEKI where VADIT_NU is null UNION ALL SELECT e.DA_NUM, e.DA_UZV, e.VADIT_NU, r.ATS_LIM+1 ATS_LIM, e.ALGA from POZ_IZV r, DARBINIEKI e WHERE r.NUM = e.VADIT_NU) SEARCH DEPTH FIRST BY UZV SET order1select LPAD(' ',2*ATS_LIM)||UZV uzvārds, NUM, VADIT, ALGAfrom POZ_IZVorder by order1;
17
The following statement shows the entire organization, indenting for each level of management, with each level ordered by hire_date. The value of is_cycle is set to Y for any employee who has the same hire_date as any manager above him in the management chain.
WITH dup_hiredate (eid, emp_last, mgr_id, reportLevel, hire_date, job_id) AS (SELECT employee_id, last_name, manager_id, 0 reportLevel, hire_date, job_id FROM employees WHERE manager_id is null UNION ALL SELECT e.employee_id, e.last_name, e.manager_id, r.reportLevel+1 reportLevel, e.hire_date, e.job_id FROM dup_hiredate r, employees e WHERE r.eid = e.manager_id) SEARCH DEPTH FIRST BY hire_date SET order1 CYCLE hire_date SET is_cycle TO 'Y' DEFAULT 'N'SELECT lpad(' ',2*reportLevel)||emp_last emp_name, eid, mgr_id, hire_date, job_id, is_cycleFROM dup_hiredateORDER BY order1;
EMP_NAME EID MGR_ID HIRE_DATE JOB_ID IS_CYCLE---------------------------------------------------------------------------------------King 100 17-JUN-03 AD_PRES N De Haan 102 100 13-JAN-01 AD_VP N Hunold 103 102 03-JAN-06 IT_PROG N Austin 105 103 25-JUN-05 IT_PROG N Kochhar 101 100 21-SEP-05 AD_VP N Mavris 203 101 07-JUN-02 HR_REP N Baer 204 101 07-JUN-02 PR_REP N Higgins 205 101 07-JUN-02 AC_MGR N Gietz 206 205 07-JUN-02 AC_ACCOUNT Y Greenberg 108 101 17-AUG-02 FI_MGR N Faviet 109 108 16-AUG-02 FI_ACCOUNT N Chen 110 108 8-SEP-05 FI_ACCOUNT N. . .
begininsert into TAB_1 values (1, NULL);insert into TAB_1 values (2, 1);insert into TAB_1 values (3, 2);insert into TAB_1 values (4, 2);insert into TAB_1 values (5, 4);insert into TAB_1 values (6, 4);insert into TAB_1 values (7, 1);insert into TAB_1 values (8, 7);insert into TAB_1 values (9, 1);insert into TAB_1 values (10, 9);insert into TAB_1 values (11, 10);insert into TAB_1 values (12, 9);end;
19
with T1(ID, VECAKA_ID) as ( -- Sākuma (enkura) loceklis. select ID, VECAKA_ID from TAB_1 where VECAKA_ID is null union all -- Rekursīvs loceklis. select t2.ID, t2.VECAKA_ID from TAB_1 t2, T1 where t2.VECAKA_ID = T1.ID)
search breadth first by ID set KARTIBA1select ID, VECAKA_IDfrom T1order by KARTIBA1;
The ordering of the rows is specified using the SEARCH clause, which can use two methods.
1) BREADTH FIRST BY : sibling rows are returned before child rows are processed.
2) DEPTH FIRST BY : child rows are returned before siblings are processed.