25
Vaicājumi ar WITH konstrukciju (subquery factoring) 1 with PROJEKTA_DARBINIEKI as select COUNT(DARBINIEKA_NUMURS) darbinieku_skaits, PROJEKTA_NOSAUKUMS from DARBINIEKI group by PROJEKTA_NOSAUKUMS PROJEKTA_DARBI as select COUNT(DARBA_NUMURS) darbu_skaits, PROJEKTA_NOSAUKUMS from DARBI group by PROJEKTA_NOSAUKUMS select A.PROJEKTA_NOSAUKUMS, A.darbinieku_skaits, B.darbu_skaits from PROJEKTA_DARBINIEKI A, PROJEKTA_DARBI B where A.PROJEKTA_NOSAUKUMS = B.PROJEKTA_NOSAUKUMS 1 http://psoug.org/reference/with.html with vaicajums_1 as ( SELECT ... ) vaicajums_2 as (SELECT ... ) 1

WITH  · Web view2018-03-30 · You can then reference the subquery block multiple places in the query by specifying query_name. Oracle Database optimizes the query by treating the

  • Upload
    lymien

  • View
    216

  • Download
    0

Embed Size (px)

Citation preview

 Vaicājumi ar WITH konstrukciju (subquery factoring)1

withPROJEKTA_DARBINIEKI asselect COUNT(DARBINIEKA_NUMURS) darbinieku_skaits, PROJEKTA_NOSAUKUMS

from DARBINIEKIgroup by PROJEKTA_NOSAUKUMS

PROJEKTA_DARBI asselect COUNT(DARBA_NUMURS) darbu_skaits, PROJEKTA_NOSAUKUMS

from DARBIgroup by PROJEKTA_NOSAUKUMS

select A.PROJEKTA_NOSAUKUMS, A.darbinieku_skaits, B.darbu_skaitsfrom PROJEKTA_DARBINIEKI A, PROJEKTA_DARBI Bwhere A.PROJEKTA_NOSAUKUMS = B.PROJEKTA_NOSAUKUMS

1 http://psoug.org/reference/with.html

with vaicajums_1 as ( SELECT ... )

vaicajums_2 as (SELECT ... )

select ... from vaicajums_1, vaicajums_2

1

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 …),     Q2() AS (SELECT ... FROM Q1   UNION ALL   SELECT ... FROM Q1)SELECT ...FROM Q1, Q2WHERE ...

WITH Q1 as (SELECT dummy FROM DUAL)SELECT dummy FROM Q1;

2

Subquery factoring_clause

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

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

8

create table DARB(DA_NUM number Primary key,DA_UZV varchar2(20),ALGA number(8,2),DE_NUM number,VAD_NU number);

insert into DARB values(1, 'Sakne', 900,1,NULL);insert into DARB values(2, 'Zars', 800,1,1);insert into DARB values(3, 'Stumrs', 800,1,1);insert into DARB values(4, 'Sakne', 600,1,2);insert into DARB values(5, 'Lapa', 600,1,2);insert into DARB values(6, 'Ozols', 800,2,1);insert into DARB values(7, 'Osis', 700,2,6);insert into DARB values(8, 'Alksnis', 700,2,6);insert into DARB values(9, 'Egle', 700,2,8);insert into DARB values(10, 'Priede', 800,3,1);insert into DARB values(11, 'Virsis', 700,3,10);insert into DARB values(12, 'Liepa', 600,3,11);

create table DEP(DE_NUM number Primary key,DE_NOS varchar2(20));

insert into DEP values(1, 'DEP1');insert into DEP values(2, 'DEP2');insert into DEP values(3, 'DEP3');

9

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 DARB a, DEP b where a.DE_NUM = b.DE_NUM group by b.DE_NOS) c UNION ALL select e.DE_NOS, SUM(d.ALGA) DE_KOPĀ, 0 from DARB d, DEP e where d.DE_NUM = e.DE_NUM group by e.DE_NOS;

10

Pakārtotais vaicājums, kas izsauc citu pakārtoto vaicājumu (subquery factoring statement) Noskaidrot departamentu, kuru darbinieku algu summa ir lielāka vai vienāda ar vidējo departamentu darbinieku algu

WITH DE_IZMAKSAS as ( select DE_NOS, SUM(ALGA) DE_KOPĀ from DARB a, DEP 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

11

Rekursīvs vaicājums ar starpniecībuNoteikt darbiniekus, kuri tieši vai netieši sniedz pārskatus 1 darbiniekam un viņu atskaišu līmeni

WITH ATSK_1 (NUM, UZV, VADIT, ATS_LIM) AS (select DA_NUM, DA_UZV, VAD_NU, 0 from DARB where DA_NUM = 1 UNION ALL select e.DA_NUM, e.DA_UZV, e.VAD_NU, ATS_LIM+1 from ATSK_1 r, DARB e where r.NUM = e.VAD_NU )

select NUM, UZV, VADIT, ATS_LIM from ATSK_1order by ATS_LIM, NUM;

12

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, VAD_NU, 0, CAST(VAD_NU as varchar2(200)) from DARB where DA_NUM= 1 UNION ALL select e.DA_NUM, e.DA_UZV, e.VAD_NU, ATS_LIM+1, CAST(VAD_SAR || ',' || VAD_NU as varchar2(200)) FROM ATSK_1 r, DARB e WHERE r.NUM = e.VAD_NU )

select NUM, UZV, VADIT, ATS_LIM, VAD_SARfrom ATSK_1order by ATS_LIM, NUM;

13

Noteikt darbiniekus, kuri tieši sniedz pārskatus galvenajam vadītājam

with ATSK_1 (NUM, UZV, VADIT, ATS_LIM, VAD_SAR) AS (select DA_NUM, DA_UZV, VAD_NU, 0, CAST(VAD_NU as varchar2(200)) from DARB where DA_NUM= 1 UNION ALL select e.DA_NUM, e.DA_UZV, e.VAD_NU, ATS_LIM+1, CAST(VAD_SAR || ',' || VAD_NU as varchar2(200)) FROM ATSK_1 r, DARB e WHERE r.NUM = e.VAD_NU )

select NUM, UZV, VADIT, ATS_LIM, VAD_SARfrom ATSK_1where ATS_LIM <=1order by ATS_LIM, NUM;

14

Grafiska darbinieku pakārtotības shemas izvade

with POZ_IZV (NUM, UZV, VADIT, ATS_LIM, ALGA) as (select DA_NUM, DA_UZV, VAD_NU, 0, ALGA from DARB where VAD_NU is null UNION ALL SELECT e.DA_NUM, e.DA_UZV, e.VAD_NU, r.ATS_LIM+1 ATS_LIM, e.ALGA from POZ_IZV r, DARB e WHERE r.NUM = e.VAD_NU) SEARCH DEPTH FIRST BY UZV SET order1

select LPAD(' ',2*ATS_LIM)||UZV uzvārds, NUM, VADIT, ALGAfrom POZ_IZVorder by order1;

15

Rekursija vienā tabulā (tabula)

create table T1 (ID number,VEC_ID number,constraint T1_PA primary key(ID),constraint T1_AA foreign key(VEC_ID) references T1(ID));

create index T1_IND on T1(VEC_ID);

begininsert into T1 values (1, NULL);insert into T1 values (2, 1);insert into T1 values (3, 2);insert into T1 values (4, 2);insert into T1 values (5, 4);insert into T1 values (6, 4);insert into T1 values (7, 1);insert into T1 values (8, 7);insert into T1 values (9, 1);insert into T1 values (10, 9);insert into T1 values (11, 10);insert into T1 values (12, 9);end;

16

Rekursīvs vaicājums vienā tabulā

with TV(ID, VEC_ID) as ( -- Sākuma (enkura) loceklis. select ID, VEC_ID from T1 where VEC_ID is null union all -- Rekursīvais loceklis. select t2.ID, t2.VEC_ID from T1 t2, TV where t2.VEC_ID = TV.ID)

search breadth first by ID set KARTIBA1select ID, VEC_IDfrom TVorder by KARTIBA1;

The ordering of the rows is specified using the SEARCH clause, which can use two methods.

1) BREADTH FIRST BY : sibling (brālis vai māsa) rows are returned before child rows are processed.

2 7 9

3 4 108

1

12

5 6 11

17

2) DEPTH FIRST BY : child rows are returned before siblings are processed.18