SlideShare a Scribd company logo
1
Oracle Database
Advanced Querying
111
Zohar Elkayam
CTO, Brillix
Zohar@Brillix.co.il
www.realdbamagic.com
Twitter: @realmgic
22
• Zohar Elkayam, CTO/COO at Brillix-DBAces
• Oracle ACE Associate
• DBA, team leader, Oracle University instructor, public
speaker, and a senior consultant for over 18 years
• Editor of ilDBA – Israel Database Community website
• Blogger – www.realdbamagic.com
Who am I?
3
We are committed to provide the highest quality of services
delivered by our dedicated team of highly trained and
experienced industry’s top data experts. We offer:
 Complete integrated end-to-end solutions based on best-of-
breed innovations in database, security and big data
technologies
 On-site professional customized trainings led by our team of
Oracle ACEs and Oracle Certified Professionals
 Comprehensive security solutions and services for leading
database platforms and business applications, leveraging a
world-class team of security experts
About Brillix
44
• Aggregative and advanced grouping options
• Analytic functions, ranking and pagination
• Hierarchical and recursive queries
• Oracle 12c new rows pattern matching feature
• XML and JSON handling with SQL
• Regular Expressions
• SQLcl – a new replacement tool for SQL*Plus
from Oracle
Agenda
55
•‫הספר‬"Oracle SQL–‫יכולות‬
‫מתקדמות‬,‫לשולף‬ ‫מדריך‬
‫המהיר‬"‫ב‬ ‫פורסם‬-2011
•‫ה‬ ‫ספר‬ ‫זה‬-SQL‫הראשון‬
‫בעברית‬ ‫שנכתב‬ ‫והיחיד‬
‫סופו‬ ‫ועד‬ ‫מתחילתו‬
•‫עמיאל‬ ‫ידי‬ ‫על‬ ‫נכתב‬ ‫הספר‬
‫שלי‬ ‫טכנית‬ ‫עריכה‬ ‫ועבר‬ ‫דיוויס‬
‫אודות‬Oracle SQL–‫מתקדמות‬ ‫יכולות‬
6
The REAL Agenda
10:30-10:45‫הפסקה‬
12:30-13:30‫משתתפ‬ ‫לכל‬ ‫צהריים‬ ‫ארוחת‬‫הכנס‬ ‫י‬
15:00-15:15‫מתוקה‬ ‫הפסקה‬
16:30‫הביתה‬ ‫הולכים‬
77
• SQL was invented in 1970 by Dr. E. F. Codd
• Each vendor had its own flavor of SQL
• Standardized by ASNI since 1986
• Current stable standard is ANSI SQL:2011/2008
• Oracle 12c is fully compliant to CORE SQL:2011
• Oracle 11g is compliant to SQL:2008
ANSI SQL
88
• In this seminar we will only talk about Queries
Queries
Group Functions
More than just group by…
9
10
• Using SQL for aggregation:
– Group functions basics
– The CUBE and ROLLUP extensions to the GROUP
BY clause
– The GROUPING functions
– The GROUPING SETS expression
• Working with composite columns
• Using concatenated groupings
Group Function and SQL
1111
• Group functions will return a single row for
each group
• The group by clause groups rows together and
allows group functions to be applied
• Common group functions: SUM, MIN, MAX,
AVG, etc.
Basics
12
Group Functions Syntax
SELECT [column,] group_function(column). . .
FROM table
[WHERE condition]
[GROUP BY group_by_expression]
[ORDER BY column];
SELECT AVG(salary), STDDEV(salary),
COUNT(commission_pct),MAX(hire_date)
FROM hr.employees
WHERE job_id LIKE 'SA%';
13
SELECT department_id, job_id, SUM(salary),
COUNT(employee_id)
FROM hr.employees
GROUP BY department_id, job_id
Order by department_id;
The GROUP BY Clause
SELECT [column,] group_function(column)
FROM table
[WHERE condition]
[GROUP BY group_by_expression]
[ORDER BY column];
14
• Use the HAVING clause to specify which
groups are to be displayed
• You further restrict the groups on the basis of
a limiting condition
The HAVING Clause
SELECT [column,] group_function(column)...
FROM table
[WHERE condition]
[GROUP BY group_by_expression]
[HAVING having_expression]
[ORDER BY column];
15
• Use ROLLUP or CUBE with GROUP BY to
produce superaggregate rows by cross-
referencing columns
• ROLLUP grouping produces a result set
containing the regular grouped rows and the
subtotal and grand total values
• CUBE grouping produces a result set
containing the rows from ROLLUP and cross-
tabulation rows
GROUP BY with the
ROLLUP and CUBE Operators
16
• ROLLUP is an extension of the GROUP BY
clause
• Use the ROLLUP operation to produce
cumulative aggregates, such as subtotals
Using the ROLLUP Operator
SELECT [column,] group_function(column). . .
FROM table
[WHERE condition]
[GROUP BY [ROLLUP] group_by_expression]
[HAVING having_expression];
[ORDER BY column];
17
Using the ROLLUP Operator: Example
SELECT department_id, job_id, SUM(salary)
FROM hr.employees
WHERE department_id < 60
GROUP BY ROLLUP(department_id, job_id);
1
2
3
Total by DEPARTMENT_ID
and JOB_ID
Total by DEPARTMENT_ID
Grand total
18
• CUBE is an extension of the GROUP BY clause
• You can use the CUBE operator to produce
cross-tabulation values with a single SELECT
statement
Using the CUBE Operator
SELECT [column,] group_function(column)...
FROM table
[WHERE condition]
[GROUP BY [CUBE] group_by_expression]
[HAVING having_expression]
[ORDER BY column];
19
1
2
3
4
Grand total
Total by JOB_ID
Total by DEPARTMENT_ID
and JOB_ID
Total by DEPARTMENT_ID
SELECT department_id, job_id, SUM(salary)
FROM hr.employees
WHERE department_id < 60
GROUP BY CUBE (department_id, job_id);
. . .
Using the CUBE Operator: Example
20
SELECT [column,] group_function(column) .. ,
GROUPING(expr)
FROM table
[WHERE condition]
[GROUP BY [ROLLUP][CUBE] group_by_expression]
[HAVING having_expression]
[ORDER BY column];
• The GROUPING function:
– Is used with the CUBE or ROLLUP operator
– Is used to find the groups forming the subtotal in a row
– Is used to differentiate stored NULL values from NULL
values created by ROLLUP or CUBE
– Returns 0 or 1
Working with the GROUPING Function
21
SELECT department_id DEPTID, job_id JOB,
SUM(salary),
GROUPING(department_id) GRP_DEPT,
GROUPING(job_id) GRP_JOB
FROM hr.employees
WHERE department_id < 50
GROUP BY ROLLUP(department_id, job_id);
Working with the GROUPING Function: Example
1
2
3
2222
• Extension to the GROUPING function
• GROUPING_ID returns a number
corresponding to the GROUPING bit vector
associated with a row
• Useful for understanding what level the row is
aggregated at and filtering those rows
Working with GROUPING_ID Function
2323
GROUPING_ID Function Example
SELECT department_id DEPTID, job_id JOB,
SUM(salary),
GROUPING_ID(department_id,job_id) GRP_ID
FROM hr.employees
WHERE department_id < 40
GROUP BY CUBE(department_id, job_id);
DEPTID JOB SUM(SALARY) GRP_ID
---------- ---------- ----------- ----------
48300 3
MK_MAN 13000 2
MK_REP 6000 2
PU_MAN 11000 2
AD_ASST 4400 2
PU_CLERK 13900 2
10 4400 1
10 AD_ASST 4400 0
20 19000 1
20 MK_MAN 13000 0
20 MK_REP 6000 0
30 24900 1
30 PU_MAN 11000 0
30 PU_CLERK 13900 0
2424
• GROUP_ID distinguishes duplicate groups
resulting from a GROUP BY specification
• A Unique group will be assigned 0, the non
unique will be assigned 1 to n-1 for n
duplicate groups
• Useful in filtering out duplicate groupings
from the query result
Working with GROUP_ID Function
2525
GROUP_ID Function Example
SELECT department_id DEPTID, job_id JOB,
SUM(salary),
GROUP_ID() UNIQ_GRP_ID
FROM hr.employees
WHERE department_id < 40
GROUP BY department_id, CUBE(department_id, job_id);
DEPTID JOB SUM(SALARY) UNIQ_GRP_ID
---------- ---------- ----------- -----------
10 AD_ASST 4400 0
20 MK_MAN 13000 0
20 MK_REP 6000 0
30 PU_MAN 11000 0
30 PU_CLERK 13900 0
10 AD_ASST 4400 1
20 MK_MAN 13000 1
20 MK_REP 6000 1
30 PU_MAN 11000 1
30 PU_CLERK 13900 1
10 4400 0
20 19000 0
30 24900 0
10 4400 1
20 19000 1
30 24900 1
26
• The GROUPING SETS syntax is used to define
multiple groupings in the same query.
• All groupings specified in the GROUPING SETS
clause are computed and the results of individual
groupings are combined with a UNION ALL
operation.
• Grouping set efficiency:
– Only one pass over the base table is required.
– There is no need to write complex UNION statements.
– The more elements GROUPING SETS has, the
greater the performance benefit.
GROUPING SETS
28
SELECT department_id, job_id,
manager_id, AVG(salary)
FROM hr.employees
GROUP BY GROUPING SETS
((department_id,job_id), (job_id,manager_id));
GROUPING SETS: Example
. . .
. . .
1
2
30
• A composite column is a collection of columns
that are treated as a unit.
ROLLUP (a,(b,c), d)
• Use parentheses within the GROUP BY clause to
group columns, so that they are treated as a unit
while computing ROLLUP or CUBE operators.
• When used with ROLLUP or CUBE, composite
columns require skipping aggregation across
certain levels.
Composite Columns
32
SELECT department_id, job_id, manager_id,
SUM(salary)
FROM hr.employees
GROUP BY ROLLUP( department_id,(job_id, manager_id));
Composite Columns: Example
…
1
2
3
4
34
• Concatenated groupings offer a concise way to
generate useful combinations of groupings.
• To specify concatenated grouping sets, you separate
multiple grouping sets, ROLLUP, and CUBE operations
with commas so that the Oracle server combines them
into a single GROUP BY clause.
• The result is a cross-product of groupings from each
GROUPING SET.
Concatenated Groupings
GROUP BY GROUPING SETS(a, b), GROUPING SETS(c, d)
35
SELECT department_id, job_id, manager_id,
SUM(salary)
FROM hr.employees
GROUP BY department_id,
ROLLUP(job_id),
CUBE(manager_id);
Concatenated Groupings: Example
…
…
…
1
3
4
5
6
2
7
…
…
Pivot and Unpivot
Turning things around!
36
PIVOT and UNPIVOT Clauses
of the SELECT Statement
• You can use the PIVOT operator of the
SELECT statement to write cross-tabulation
queries that rotate the column values into new
columns, aggregating data in the process.
• You can use the UNPIVOT operator of the
SELECT statement to rotate columns into
values of a column.
PIVOT UNPIVOT
38
Pivoting on the QUARTER
Column: Conceptual Example
30,000
40,000
60,000
30,000
40,000
20,000
AMOUNT_
SOLD
2,500Q1IUSAKids Jeans
2,000Q2CJapanKids Jeans
2,000Q3SUSAShorts
I
P
C
CHANNEL
Kids Jeans
Shorts
Shorts
PRODUCT
1,000Q2Germany
1,500Q4USA
Q2
QUARTER
2,500Poland
QUANTITY_
SOLD
COUNTRY
2,000
Q3
Kids Jeans
Shorts
PRODUCT
3,500
2,000
Q2
1,5002,500
Q4Q1
3939
• Pivoting the data before 11g was a complex
query which required the use of the CASE or
DECODE functions
Pivoting Before Oracle 11g
select product,
sum(case when quarter = 'Q1' then amount_sold else null end) Q1,
sum(case when quarter = 'Q2' then amount_sold else null end) Q2,
sum(case when quarter = 'Q3' then amount_sold else null end) Q3,
sum(case when quarter = 'Q4' then amount_sold else null end) Q4
from sales
group by product;
40
Pivot Clause Syntax
table_reference PIVOT [ XML ]
( aggregate_function ( expr ) [[AS] alias ]
[, aggregate_function ( expr ) [[AS] alias ] ]...
pivot_for_clause
pivot_in_clause )
-- Specify the column(s) to pivot whose values are to
-- be pivoted into columns.
pivot_for_clause =
FOR { column |( column [, column]... ) }
-- Specify the pivot column values from the columns you
-- specified in the pivot_for_clause.
pivot_in_clause =
IN ( { { { expr | ( expr [, expr]... ) } [ [ AS] alias] }...
| subquery | { ANY | ANY [, ANY]...} } )
42
Creating a New View: Example
CREATE OR REPLACE VIEW sales_view AS
SELECT
prod_name AS product,
country_name AS country,
channel_id AS channel,
SUBSTR(calendar_quarter_desc, 6,2) AS quarter,
SUM(amount_sold) AS amount_sold,
SUM(quantity_sold) AS quantity_sold
FROM sales, times, customers, countries, products
WHERE sales.time_id = times.time_id AND
sales.prod_id = products.prod_id AND
sales.cust_id = customers.cust_id AND
customers.country_id = countries.country_id
GROUP BY prod_name, country_name, channel_id,
SUBSTR(calendar_quarter_desc, 6, 2);
44
Selecting the SALES VIEW Data
SELECT product, country, channel, quarter, quantity_sold
FROM sales_view;
PRODUCT COUNTRY CHANNEL QUARTER QUANTITY_SOLD
------------ ------------ ---------- -------- -------------
Y Box Italy 4 01 21
Y Box Italy 4 02 17
Y Box Italy 4 03 20
. . .
Y Box Japan 2 01 35
Y Box Japan 2 02 39
Y Box Japan 2 03 36
Y Box Japan 2 04 46
Y Box Japan 3 01 65
. . .
Bounce Italy 2 01 34
Bounce Italy 2 02 43
. . .
9502 rows selected.
45
Pivoting the QUARTER Column
in the SH Schema: Example
SELECT *
FROM
(SELECT product, quarter, quantity_sold
FROM sales_view) PIVOT (sum(quantity_sold)
FOR quarter IN ('01', '02', '03', '04'))
ORDER BY product DESC;
. . .
47
Unpivoting the QUARTER Column:
Conceptual Example
2,000
Q3
Kids Jeans
Shorts
PRODUCT
3,500
2,000
Q2
1,5002,500
Q4Q1
2,500Q1Kids Jeans
2,000Q2Kids Jeans
3,500Q2Shorts
1,500Q4Kids Jeans
Q3
QUARTER
2,000Shorts
SUM_OF_QUANTITYPRODUCT
4848
• Univoting the data before 11g requires
multiple queries on the table using the
UNION ALL operator
Unpivoting Before Oracle 11g
SELECT *
FROM (
SELECT product, '01' AS quarter, Q1_value FROM sales
UNION ALL
SELECT product, '02' AS quarter, Q2_value FROM sales
UNION ALL
SELECT product, '03' AS quarter, Q3_value FROM sales
UNION ALL
SELECT product, '04' AS quarter, Q4_value FROM sales
);
49
• An UNPIVOT operation does not reverse a
PIVOT operation; instead, it rotates data found
in multiple columns of a single row into multiple
rows of a single column.
• If you are working with pivoted data, UNPIVOT
cannot reverse any aggregations that have been
made by PIVOT or any other means.
Using the UNPIVOT Operator
UNPIVOT
50
• The UNPIVOT clause rotates columns from a
previously pivoted table or a regular table into
rows. You specify:
– The measure column or columns to be unpivoted
– The name or names for the columns that result from
the UNPIVOT operation
– The columns that are unpivoted back into values of
the column specified in pivot_for_clause
• You can use an alias to map the column name to
another value.
Using the UNPIVOT Clause
51
UNPIVOT Clause Syntax
table_reference UNPIVOT [{INCLUDE|EXCLUDE} NULLS]
-- specify the measure column(s) to be unpivoted.
( { column | ( column [, column]... ) }
unpivot_for_clause
unpivot_in_clause )
-- Specify one or more names for the columns that will
-- result from the unpivot operation.
unpivot_for_clause =
FOR { column | ( column [, column]... ) }
-- Specify the columns that will be unpivoted into values of
-- the column specified in the unpivot_for_clause.
unpivot_in_clause =
( { column | ( column [, column]... ) }
[ AS { constant | ( constant [, constant]... ) } ]
[, { column | ( column [, column]... ) }
[ AS { constant | ( constant [, constant]...) } ] ]...)
52
Creating a New Pivot Table: Example
. . .
CREATE TABLE pivotedtable AS
SELECT *
FROM
(SELECT product, quarter, quantity_sold
FROM sales_view) PIVOT (sum(quantity_sold)
FOR quarter IN ('01' AS Q1, '02' AS Q2,
'03' AS Q3, '04' AS Q4));
SELECT * FROM pivotedtable
ORDER BY product DESC;
53
Unpivoting the QUARTER Column
in the SH Schema: Example
SELECT *
FROM pivotedtable
UNPIVOT (quantity_sold For Quarter IN (Q1, Q2, Q3, Q4))
ORDER BY product DESC, quarter;
. . .
5454
• More information and examples could be
found on my Blog:
http://www.realdbamagic.com/he/pivot-a-table/
More Examples…
Analytic Functions
Let’s analyze our data!
55
56
• Oracle has enhanced SQL's analytical processing
capabilities by introducing a new family of analytic SQL
functions.
• These analytic functions enable you to calculate and
perform:
– Rankings and percentiles
– Pivoting operations
– Moving window calculations
– LAG/LEAD analysis
– FIRST/LAST analysis
– Linear regression statistics
Overview of SQL for Analysis and Reporting
5757
• Ability to see one row from another row in the
results
• Avoid self-join queries
• Summary data in detail rows
• Slice and dice within the results
Why Use Analytic Functions?
58
Using the Analytic Functions
Function type Used for
Ranking Calculating ranks, percentiles, and n-tiles of the values in a
result set
Windowing Calculating cumulative and moving aggregates, works with
functions such as SUM, AVG, MIN, and so on
Reporting Calculating shares such as market share, works with
functions such as SUM, AVG, MIN, MAX, COUNT, VARIANCE,
STDDEV, RATIO_TO_REPORT, and so on
LAG/LEAD Finding a value in a row or a specified number of rows
from a current row
FIRST/LAST First or last value in an ordered group
Linear Regression Calculating linear regression and other statistics
59
• Result set partitions: These are created and available
to any aggregate results such as sums and averages.
The term “partitions” is unrelated to the table
partitions feature.
• Window: For each row in a partition, you can define a
sliding window of data, which determines the range of
rows used to perform the calculations for the current
row.
• Current row: Each calculation performed with an
analytic function is based on a current row within a
partition. It serves as the reference point determining
the start and end of the window.
Concepts Used in Analytic Functions
61
• We can use aggregative functions as analytic
functions (i.e. SUM, AVG, MIN, MAX, COUNT
etc.)
• Each row will get the aggregative value for a
given partition without the need for group by
clause
Reporting Functions
62
• We can have multiple group by on the same row
• Getting the raw data along with the aggregated
value
Reporting Example
SELECT last_name, salary,
ROUND(AVG(salary) OVER (PARTITION BY department_id),2),
COUNT(*) OVER (PARTITION BY manager_id),
SUM(salary) OVER (PARTITION BY department_id ORDER BY salary),
MAX(salary) OVER ()
FROM hr.employees;
Ranking Functions
64
• A ranking function computes the rank of a
record compared to other records in the data
set based on the values of a set of measures.
The types of ranking function are:
– RANK and DENSE_RANK functions
– PERCENT_RANK function
– ROW_NUMBER function
– NTILE function
– CUME_DIST function
Using the Ranking Functions
65
• The RANK function calculates the rank of a value in a group
of values, which is useful for top-N and bottom-N reporting.
• For example, you can use the RANK function to find the top
ten products sold in Boston last year.
• When using the RANK function, ascending is the default
sort order, which you can change to descending.
• Rows with equal values for the ranking criteria receive the
same rank.
• Oracle Database then adds the number of tied rows to the
tied rank to calculate the next rank.
Working with the RANK Function
RANK ( ) OVER ( [query_partition_clause] order_by_clause )
66
Using the RANK Function: Example
SELECT department_id, last_name, salary,
RANK() OVER (PARTITION BY department_id
ORDER BY salary DESC) "Rank"
FROM employees
WHERE department_id = 60
ORDER BY department_id, "Rank", salary;
67
• The RANK function can be made to operate
within groups—that is, the rank gets reset
whenever the group changes.
• This is accomplished with the PARTITION BY
clause.
• The group expressions in the PARTITION BY
subclause divide the data set into groups within
which RANK operates.
• For example, to rank products within each
channel by their dollar sales, you could issue a
statement similar to the one in the next slide.
Per-Group Ranking
68
Per-Group Ranking: Example
SELECT channel_desc, calendar_month_desc, TO_CHAR(SUM(amount_sold),
'9,999,999,999') SALES$, RANK() OVER (PARTITION BY channel_desc
ORDER BY SUM(amount_sold) DESC) AS RANK_BY_CHANNEL
FROM sales, products, customers, times, channels
WHERE sales.prod_id = products.prod_id
AND sales.cust_id = customers.cust_id
AND sales.time_id = times.time_id
AND sales.channel_Id = channels.channel_id
AND times.calendar_month_desc IN ('2000-08', '2000-09', '2000-
10', '2000-11')
AND channels.channel_desc IN ('Direct Sales', 'Internet')
GROUP BY channel_desc, calendar_month_desc;
69
RANK and DENSE_RANK Functions: Example
SELECT department_id, last_name, salary,
RANK() OVER (PARTITION BY department_id
ORDER BY salary DESC) "Rank",
DENSE_RANK() over (partition by department_id
ORDER BY salary DESC) "Drank"
FROM employees
WHERE department_id = 60
ORDER BY department_id, last_name, salary DESC, "Rank"
DESC;
DENSE_RANK ( ) OVER ([query_partition_clause] order_by_clause)
70
Per-Cube and Rollup Group Ranking
SELECT channel_desc, country_iso_code,
TO_CHAR(SUM(amount_sold), '9,999,999,999')SALES$,
RANK() OVER
(PARTITION BY GROUPING_ID(channel_desc, country_iso_code)
ORDER BY SUM(amount_sold) DESC) AS RANK_PER_GROUP
FROM sales, customers, times, channels, countries
WHERE sales.time_id = times.time_id AND
sales.cust_id=customers.cust_id AND
sales.channel_id = channels.channel_id AND
channels.channel_desc IN ('Direct Sales', 'Internet') AND
times.calendar_month_desc='2000-09' AND
country_iso_code IN ('GB', 'US', 'JP')
GROUP BY CUBE(channel_desc, country_iso_code);
71
• Uses rank values in its numerator and returns the
percent rank of a value relative to a group of values
• PERCENT_RANK of a row is calculated as follows:
• The range of values returned by PERCENT_RANK is 0
to 1, inclusive. The first row in any set has a
PERCENT_RANK of 0. The return value is NUMBER. Its
syntax is:
Using the PERCENT_RANK Function
(rank of row in its partition - 1) / (number of rows in
the partition - 1)
PERCENT_RANK () OVER ([query_partition_clause]
order_by_clause)
72
Using the PERCENT_RANK Function: Example
SELECT department_id, last_name, salary, PERCENT_RANK()
OVER (PARTITION BY department_id ORDER BY salary DESC)
AS pr
FROM hr.employees
ORDER BY department_id, pr, salary;
. . .
73
• The ROW_NUMBER function calculates a
sequential number of a value in a group of
values.
• When using the ROW_NUMBER function,
ascending is the default sort order, which you
can change to descending.
• Rows with equal values for the ranking criteria
receive a different number.
Working with the ROW_NUMBER Function
ROW_NUMBER ( ) OVER ( [query_partition_clause] order_by_clause )
7474
• ROWNUM is a pseudo column, ROW_NUMBER
is an actual function
• ROWNUM requires sorting of the entire dataset
in order to return ordered list
• ROW_NUMBER will only sort the required rows
thus giving better performance
ROW_NUMBER vs. ROWNUM
7575
• Not really a rank function
• Divides an ordered data set into a number of
buckets indicated by expr and assigns the
appropriate bucket number to each row
• The buckets are numbered 1 through expr
Working with the NTILE Function
NTILE ( expr ) OVER ([query_partition_clause] order_by_clause)
7676
• Different ranking functions may return
different results if the data has ties
• For example:
Summary of Ranking Functions
SELECT last_name, salary,
ROW_NUMBER() OVER (PARTITION BY department_id ORDER BY salary DESC),
RANK() OVER (PARTITION BY department_id ORDER BY salary DESC),
DENSE_RANK() OVER (PARTITION BY department_id ORDER BY salary DESC),
PERCENT_RANK() OVER (PARTITION BY department_id ORDER BY salary DESC),
NTILE(4) OVER (PARTITION BY department_id ORDER BY salary DESC)
FROM hr.employees;
Inter-row Analytic Functions
77
78
• LAG provides access to more than one row of a table
at the same time without a self-join.
• Given a series of rows returned from a query and a
position of the cursor, LAG provides access to a row at
a given physical offset before that position.
• If you do not specify the offset, its default is 1.
• If the offset goes beyond the scope of the window, the
optional default value is returned. If you do not specify
the default, its value is NULL.
Using the LAG and LEAD Analytic Functions
{LAG | LEAD}(value_expr [, offset ] [, default ])
OVER ([ query_partition_clause ] order_by_clause)
79
Using the LAG and LEAD Analytic Functions:
Example
SELECT time_id, TO_CHAR(SUM(amount_sold),'9,999,999') AS
SALES,
TO_CHAR(LAG(SUM(amount_sold),1) OVER (ORDER BY
time_id),'9,999,999') AS LAG1,
TO_CHAR(LEAD(SUM(amount_sold),1) OVER (ORDER BY
time_id),'9,999,999') AS LEAD1
FROM sales
WHERE time_id >= TO_DATE('10-OCT-2000') AND
time_id <= TO_DATE('14-OCT-2000')
GROUP BY time_id;
8080
• For a specified measure, LISTAGG orders data
within each group specified in the ORDER BY
clause and then concatenates the values of
the measure column
• Limited to output of 4000 chars
Using the LISTAGG Function
LISTAGG(measure_expr [, 'delimiter'])
WITHIN GROUP (order_by_clause) [OVER
query_partition_clause]
8181
Using the LISTAGG Function Example
SELECT department_id "Dept", hire_date "Date",
last_name "Name",
LISTAGG(last_name, ', ') WITHIN GROUP (ORDER BY
hire_date, last_name)
OVER (PARTITION BY department_id) as "Emp_list"
FROM hr.employees
WHERE hire_date < '01-SEP-2003'
ORDER BY "Dept", "Date", "Name";
8282
• Both are aggregate and analytic functions
• Used to retrieve a value from the first or last row
of a sorted group, but the needed value is not the
sort key
• FIRST and LAST functions eliminate the need for
self-joins or views and enable better performance
Using the FIRST and LAST Functions
aggregate_function KEEP
(DENSE_RANK FIRST ORDER BY
expr [ DESC | ASC ][ NULLS { FIRST | LAST } ]
[, expr [ DESC | ASC ] [ NULLS { FIRST | LAST } ]
]...
)
[ OVER query_partition_clause ]
8383
FIRST and LAST Aggregate Example
SELECT department_id,
MIN(salary) KEEP (DENSE_RANK FIRST ORDER BY commission_pct)
"Worst",
MAX(salary) KEEP (DENSE_RANK LAST ORDER BY commission_pct)
"Best"
FROM employees
GROUP BY department_id
ORDER BY department_id;
8484
FIRST and LAST Analytic Example
SELECT last_name, department_id, salary,
MIN(salary) KEEP (DENSE_RANK FIRST ORDER BY
commission_pct) OVER (PARTITION BY department_id)
“Worst",
MAX(salary) KEEP (DENSE_RANK LAST ORDER BY commission_pct)
OVER (PARTITION BY department_id) "Best"
FROM employees
ORDER BY department_id, salary, last_name;
8585
• Returns the first value in an ordered set of
values
• If the first value in the set is null, then the
function returns NULL unless you specify
IGNORE NULLS. This setting is useful for data
densification.
Using FIRST_VALUE Analytic Function
FIRST_VALUE (expr [ IGNORE NULLS ]) OVER (analytic_clause)
8686
Using FIRST_VALUE Analytic Function
Example
SELECT department_id, last_name, salary,
FIRST_VALUE(last_name) OVER (ORDER BY salary ASC ROWS
UNBOUNDED PRECEDING) AS lowest_sal
FROM (SELECT * FROM employees WHERE department_id = 30
ORDER BY employee_id)
ORDER BY department_id, last_name, salary, lowest_sal;
8787
• Returns the last value in an ordered set of
values.
Using LAST_VALUE Analytic Function
LAST_VALUE (expr [ IGNORE NULLS ]) OVER (analytic_clause)
8888
• Returns the N-th values in an ordered set of
values
• Different default window: RANGE BETWEEN
UNBOUNDED PRECEDING AND CURRENT
ROW
Using NTH_VALUE Analytic Function
NTH_VALUE (measure_expr, n)
[ FROM { FIRST | LAST } ][ { RESPECT | IGNORE } NULLS ]
OVER (analytic_clause)
8989
Using NTH_VALUE Analytic Function
Example
SELECT prod_id, channel_id, MIN(amount_sold),
NTH_VALUE ( MIN(amount_sold), 2) OVER (PARTITION BY
prod_id ORDER BY channel_id
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED
FOLLOWING) nv
FROM sh.sales
WHERE prod_id BETWEEN 13 and 16
GROUP BY prod_id, channel_id;
Window Functions
9191
• The windowing_clause gives some
analytic functions a further degree of control
over this window within the current partition
• The windowing_clause can only be used
if an order_by_clause is present
Window Functions
9292
Windows can be by RANGE or ROWS
Possible values for start_point and end_point
UNBOUNDED PRECEDING The window starts at the first row of the partition.
Only available for start points.
UNBOUNDED FOLLOWING The window ends at the last row of the partition. Only
available for end points.
CURRENT ROW The window starts or ends at the current row
value_expr PRECEDING A physical or logical offset before the current row.
When used with RANGE, can also be an interval literal
value_expr FOLLOWING As above, but an offset after the current row
RANGE BETWEEN start_point AND end_point
ROWS BETWEEN start_point AND end_point
9393
• The windows are limited to the current
partition
• Generally, the default window is the entire
work set unless said otherwise
Window Limitations
9494
Shortcuts
• Useful shortcuts for the windowing clause:
ROWS UNBOUNDED PRECEDING ROWS BETWEEN UNBOUNDED
PRECEDING AND CURRENT ROW
ROWS 10 PRECEDING ROWS BETWEEN 10 PRECEDING AND
CURRENT ROW
ROWS CURRENT ROW ROWS BETWEEN CURRENT ROW AND
CURRENT ROW
9595
• Cumulative aggregation
• Sliding average over proceeding and/or
following rows
• Using the RANGE parameter to filter
aggregation records
Windowing Clause Useful Usages
Top-N and Paging Queries
In Oracle 12c
96
97
Top-N Queries
• A Top-N query is used to retrieve the top or
bottom N rows from an ordered set
• Combining two Top-N queries gives you the
ability to page through an ordered set
• Oracle 12c has introduced the row limiting
clause to simplify Top-N queries
9898
• This is ANSI syntax
• The default offset is 0
• Null values in offset, rowcount or percent
will return no rows
Top-N in 12c
[ OFFSET offset { ROW | ROWS } ]
[ FETCH { FIRST | NEXT } [ { rowcount | percent PERCENT } ]
{ ROW | ROWS } { ONLY | WITH TIES } ]
9999
Top-N Examples
SELECT last_name, salary
FROM hr.employees
ORDER BY salary
FETCH FIRST 4 ROWS ONLY;
SELECT last_name, salary
FROM hr.employees
ORDER BY salary
FETCH FIRST 4 ROWS WITH TIES;
SELECT last_name, salary
FROM hr.employees
ORDER BY salary DESC
FETCH FIRST 10 PERCENT ROWS ONLY;
100100
• Before 12c we had to use the rownum pseudo
column to filter out rows
• That will require sorting the entire rowset
Paging Before 12c
SELECT val
FROM (SELECT val, rownum AS rnum
FROM (SELECT val
FROM rownum_order_test
ORDER BY val)
WHERE rownum <= 10)
WHERE rnum >= 5;
101101
• After 12c we have a syntax improvement for
paging using the Top-N queries
• This will use ROW_NUMBER and RANK in the
background – there is no real optimization
improvements
Paging in Oracle 12c
SELECT val
FROM rownum_order_test
ORDER BY val
OFFSET 4 ROWS FETCH NEXT 5 ROWS ONLY;
102102
• More information and examples could be
found on my blog:
http://www.realdbamagic.com/he/12c-top-n-query/
More Examples
103103
• Analytic functions has positive impact on
performance for the most part
• Using analytic functions can reduce the number
of table scans and reduce IO consumption
• The query might use more CPU and/or memory
but it will usually run faster than the same result
without analytic functions
• Top-N queries might struggle with cardinality
evaluation when using the “With Ties” option
Analytic Functions and Performance
Hierarchical Queries
104
105
• You can use hierarchical queries to retrieve data based
on a natural hierarchical relationship between rows in
a table.
• A relational database does not store records in a
hierarchical way; therefore, a hierarchical query is
possible only when a relationship exists between rows
in a table.
• However, where a hierarchical relationship exists
between the rows of a single table, a process called
“tree walking” enables the hierarchy to be constructed.
• A hierarchical query is a method of reporting, with the
branches of a tree in a specific order.
Using Hierarchical Queries
106106
• Getting all employees that report directly or
indirectly to a manager
• Managing documents and folders
• Managing privileges
• Aggregating levels on the same row
Business Challenges
Using Hierarchical Queries: Example
Sample Data from the EMPLOYEES Table
• In the EMPLOYEES table in the HR schema,
Kochhar, De Haan, and Hartstein report to the
MANAGER_ID 100, which is King’s EMPLOYEE_ID.
…
108
Natural Tree Structure
De Haan
HunoldWhalen
Kochhar
Higgins
Mourgos Zlotkey
Rajs Davies Matos
Gietz Ernst Lorentz
Hartstein
Fay
Abel Taylor Grant
Vargas
MANAGER_ID = 100
(Child)
EMPLOYEE_ID = 100
(Parent)
. . . . . .
. . .
. . .
. . .
King
109
condition:
Hierarchical Queries: Syntax
expr comparison_operator expr
SELECT [LEVEL], column, expr...
FROM table
[WHERE condition(s)]
[START WITH condition(s)]
[CONNECT BY PRIOR condition(s)] ;
110
– Use the START WITH clause to specify the starting
point, that is, the row or rows to be used as the root
of the tree:
• Specifies the condition that must be met
• Accepts any condition that is valid in a WHERE clause
– For example, using the HR.EMPLOYEES table, start
with the employee whose last name is Kochhar.
Walking the Tree:
Specifying the Starting Point
. . .
START WITH last_name = 'Kochhar'
START WITH column1 = value
111
• The direction of the query is determined by the
CONNECT BY PRIOR column placement.
• The PRIOR operator refers to the parent row.
• For example, you can walk the tree from top
down using the EMPLOYEES table as follows:
Walking the Tree:
Specifying the Direction of the Query
CONNECT BY PRIOR column1 = column2
. . .
CONNECT BY PRIOR employee_id = manager_id
. . .
Parent key Child key
112
Hierarchical Query Example:
Using the CONNECT BY Clause
SELECT employee_id, last_name, manager_id
FROM hr.employees
CONNECT BY PRIOR employee_id = manager_id;
. . .
113
Specifying the Direction of the Query:
From the Top Down
SELECT last_name||' reports to '||
PRIOR last_name "Walk Top Down"
FROM hr.employees
START WITH last_name = 'King'
CONNECT BY PRIOR employee_id = manager_id ;
. . .
114
Specifying the Direction of the Query:
From the Bottom Up
SELECT employee_id, last_name, job_id, manager_id
FROM hr.employees
START WITH employee_id = 101
CONNECT BY PRIOR manager_id = employee_id ;
115
Using the LEVEL Pseudocolumn
Level 1
root/
parent
Level 3
parent/
child/leaf
Level 4
leaf
De Haan
King
HunoldWhalen
Kochhar
Higgins
Mourgos Zlotkey
Rajs Davies Matos
Gietz Ernst Lorentz
Hartstein
Fay
Abel Taylor Grant
Vargas
Level 2
parent/
child
116
Using the LEVEL Pseudocolumn: Example
SELECT employee_id, last_name, manager_id, LEVEL
FROM hr.employees
START WITH employee_id = 100
CONNECT BY PRIOR employee_id = manager_id
ORDER siblings BY last_name;
. . .
117
• Create a report displaying company
management levels beginning with the highest
level and indenting each of the following levels.
Formatting Hierarchical Reports
Using LEVEL and LPAD
SELECT LPAD(last_name, LENGTH(last_name)+(LEVEL*2)-
2,'_') AS org_chart
FROM hr.employees
START WITH first_name = 'Steven' AND last_name = 'King'
CONNECT BY PRIOR employee_id = manager_id
ORDER SIBLINGS BY last_name;
118
– Use the WHERE clause to eliminate a node.
– Use the CONNECT BY clause to eliminate a
branch.
Pruning Nodes and Branches
Kochhar
Higgins
Gietz
Whalen
Kochhar
HigginsWhalen
Gietz
. . .
WHERE last_name != 'Higgins'
. . .
CONNECT BY PRIOR employee_id = manager_id
AND last_name != 'Higgins'
1 2
119
Pruning Branches Example 1:
Eliminating a Node
SELECT department_id, employee_id,last_name, job_id,
salary
FROM hr.employees
WHERE last_name != 'Higgins'
START WITH manager_id IS NULL
CONNECT BY PRIOR employee_id = manager_id;
. . .
. . .
. . .
120
Pruning Branches Example 2:
Eliminating a Branch
SELECT department_id, employee_id,last_name, job_id,
salary
FROM hr.employees
START WITH manager_id IS NULL
CONNECT BY PRIOR employee_id = manager_id
AND last_name != 'Higgins';
. . .
121121
• Join happens before connect by
• Where is happening after connect by
• Regular order by will rearrange the
returning rows
• Sibling order by will rearrange the
returning rows for each level
Order of Precedence
122122
Other Connect By Functions
• CONNECT_BY_ISCYCLE
• CONNECT_BY_ISLEAF
• CONNECT_BY_ROOT
• SYS_CONNECT_BY_PATH
123123
• ANSI SQL:2008 (Oracle 11g) introduced a new
way to run hierarchical queries: Recursive
Subquery Factoring (RSF)
• Using the with clause, making queries easier
to write
New Syntax: Recursive Subquery Factoring
124124
Recursive Subquery Factoring Example
with mytree(id, parent_id, "level")
as
(
select id, parent_id, 1 as "level"
from temp_v
where id = 1
union all
select temp_v.id, temp_v.parent_id,
mytree."level" + 1
from temp_v, mytree
where temp_v.parent_id = mytree.id
)
Select * from mytree;
Stop Condition
Actual
Recursion
125125
• Recursion and Hierarchies might have bad
impact on performance
• Watch out for mega-trees – it has CPU and
memory impact
• Using recursion might lead for multiple IO
reads of the same blocks
Warning: Recursion
might be Bad for Performance
Pattern Matching in
Oracle 12c
126
127127
• Identify and group rows with consecutive values
• Consecutive in this regards – row after row
• Uses regular expression like syntax to find
patterns
What is Pattern Matching
128128
• Finding sequences of events in security
applications
• Locating dropped calls in a CDR listing
• Financial price behaviors (V-shape, W-shape
U-shape, etc.)
• Fraud detection and sensor data analysis
Common Business Challenges
129129
MATCH_RECOGNIZE Syntax
SELECT
FROM [row pattern input table]
MATCH_RECOGNIZE
( [ PARTITION BY <cols> ]
[ ORDER BY <cols> ]
[ MEASURES <cols> ]
[ ONE ROW PER MATCH | ALL ROWS PER MATCH ]
[ SKIP_TO_option]
PATTERN ( <row pattern> )
DEFINE <definition list>
)
130130
• PARTITION BY divides the data in to logical groups
• ORDER BY orders the data in each logical group
• MEASURES define the data measures of the pattern
• ONE/ALL ROW PER MATCH defines what to do with the
pattern – return one row or all rows
• PATTERN says what the pattern actually is
• DEFINE gives us the condition that must be met for a
row to map to the pattern variables
Basix Syntax Legend
131131
• Find Simple V-Shape with 1 row output per
match
MATCH_RECOGNIZE Example
SELECT *
FROM Ticker MATCH_RECOGNIZE (
PARTITION BY symbol
ORDER BY tstamp
MEASURES STRT.tstamp AS start_tstamp,
LAST(DOWN.tstamp) AS bottom_tstamp,
LAST(UP.tstamp) AS end_tstamp
ONE ROW PER MATCH
AFTER MATCH SKIP TO LAST UP
PATTERN (STRT DOWN+ UP+)
DEFINE
DOWN AS DOWN.price < PREV(DOWN.price),
UP AS UP.price > PREV(UP.price)
) MR
ORDER BY MR.symbol, MR.start_tstamp;
132132
What Will Be Matched?
133133
• Our goal: find uninterrupted sequences in a
book
• This can be useful for detecting missing
records or sequential behavior
Pages in a Book Example
134
Building Our Query
1. Define input
2. Pattern Matching
3. Order input
4. Process pattern
5. using defined conditions
6. Output: rows per match
7. Output: columns per row
8. Where to go after match?
SELECT *
FROM book_pages
MATCH_RECOGNIZE (
ORDER BY page
PATTERN (A B*)
DEFINE B AS page = PREV(page)+1
ONE ROW PER MATCH
MEASURES
A.page firstpage,
LAST(page) lastpage,
COUNT(*) cnt
AFTER MATCH SKIP PAST LAST ROW
);
SELECT *
FROM book_pages
MATCH_RECOGNIZE (
ORDER BY page
MEASURES
A.page firstpage,
LAST(page) lastpage,
COUNT(*) cnt
ONE ROW PER MATCH
AFTER MATCH SKIP PAST LAST ROW
PATTERN (A B*)
DEFINE B AS page = PREV(page)+1
);
135135135135
And The Output…
FIRSTPAGE LASTPAGE CNT
---------- ---------- ----------
1 3 3
5 7 3
10 15 6
42 42 1
136136136136
• Concatenation: No operator between elements.
• Quantifiers:
– * 0 or more matches.
– + 1 or more matches
– ? 0 or 1 match.
– {n} Exactly n matches.
– {n,} n or more matches.
– {n, m} Between n and m (inclusive) matches.
– {, m} Between 0 an m (inclusive) matches.
• Alternation: |
• Grouping: ()
Supported Regular Expression Patterns
137137
• CLASSIFIER(): Which pattern variable applies to which row
• MATCH_NUMBER(): Which rows are members of which match
• PREV(): Access to a column/expression in a previous row
• NEXT(): Access to a column/expression in the next row
• LAST(): Last value within the pattern match
• FIRST(): First value within the pattern match
• COUNT(), AVG(), MAX(), MIN(), SUM()
Functions
138138
• Find suspicious transfers – a large transfer after 3
small ones
Example: All Rows Per Match
SELECT userid, match_id, pattern_variable, time, amount
FROM (SELECT * FROM event_log
WHERE event = 'transfer')
MATCH_RECOGNIZE
(
PARTITION BY userid ORDER BY time
MEASURES
MATCH_NUMBER() match_id,
CLASSIFIER() pattern_variable
ALL ROWS PER MATCH
PATTERN ( x{3,} y)
DEFINE
x AS (amount < 2000 AND LAST(x.time) -FIRST(x.time) < 30),
y AS (amount >= 1000000 AND y.time-LAST(x.time) < 10)
);
139139
• MATCH_ID shows current match sequence
• PATTERN_VARIABLE show which variable was
applied
• USERID is the partition key
The Output
USERID MATCH_ID PATTERN_VA TIME AMOUNT
-------- ---------- ---------- --------- ----------
john 1 X 06-JAN-12 1000
john 1 X 15-JAN-12 1500
john 1 X 20-JAN-12 1500
john 1 X 23-JAN-12 1000
john 1 Y 26-JAN-12 1000000
140140
• Same as before – show one row per match
Example: One Row Per Match
SELECT userid, first_trx, last_trx, amount
FROM (SELECT * FROM event_log WHERE event = 'transfer')
MATCH_RECOGNIZE
(
PARTITION BY userid ORDER BY time
MEASURES
FIRST(x.time) first_trx,
y.time last_trx,
y.amount amount
ONE ROW PER MATCH
PATTERN ( x{3,} y )
DEFINE
x AS (amount < 2000 AND LAST(x.time) -FIRST(x.time) < 30),
y AS (amount >= 1000000 AND y.time-LAST(x.time) < 10)
);
141141
• USERID is the partition key
• FIRST_TRX is a calculated measure
• AMOUNT and LAST_TRX are measures
The Output
USERID FIRST_TRX LAST_TRX AMOUNT
-------- --------- --------- ----------
john 06-JAN-12 26-JAN-12 1000000
142142
• Test all cases: pattern matching can be very tricky
• Don’t forget to test your data with no matches
• There is no LISTAGG and no DISTINCT when
using match recognition
• Pattern variables cannot be used as bind
variables
Few Last Tips
Using XML with SQL
143
144144
• XML stand for Extensible Markup Language
• Defines a set of rules for encoding documents
in a format which is both human-readable and
machine-readable
• Data is unstructured and can be transferred
easily to other system
What is XML
145145
• Root
• Element
• Attribute
• Forest
• XML Fragment
• XML Document
XML Terminology
146146
What Does XML Look Like?
<?xml version="1.0"?>
<ROWSET>
<ROW>
<USERNAME>SYS</USERNAME>
<USER_ID>0</USER_ID>
<CREATED>28-JAN-08</CREATED>
</ROW>
<ROW>
<USERNAME>SYSTEM</USERNAME>
<USER_ID>5</USER_ID>
<CREATED>28-JAN-08</CREATED>
</ROW>
</ROWSET>
147147
• Concatenating strings – building the XML
manually. This is highly not recommended
• Using DBMS_XMLGEN
• Using ANSI SQL:2003 XML functions
Generating XML From Oracle
148148
• The DBMS_XMLGEN package converts the
results of a SQL query to a canonical XML
format
• The package takes an arbitrary SQL query as
input, converts it to XML format, and returns
the result as a CLOB
• Using the DBMS_XMLGEN we can create
contexts and use it to build XML documents
• Old package – exists since Oracle 9i
Using DBMS_XMLGEN
149149
Example of Using DBMS_XMLGEN
select dbms_xmlgen.getxml(q'{
select column_name, data_type
from all_tab_columns
where table_name = 'EMPLOYEES' and owner = 'HR'}')
from dual
/
<?xml version="1.0"?>
<ROWSET>
<ROW>
<COLUMN_NAME>EMPLOYEE_ID</COLUMN_NAME>
<DATA_TYPE>NUMBER</DATA_TYPE>
</ROW>
<ROW>
<COLUMN_NAME>FIRST_NAME</COLUMN_NAME>
<DATA_TYPE>VARCHAR2</DATA_TYPE>
</ROW>
[...]
</ROWSET>
150150
• DBMS_XMLGEN is an old package (9.0 and 9i)
• Any context change requires complex PL/SQL
• There are improved ways to use XML in
queries
• Use DBMS_XMLGEN for the “quick and dirty”
solution only
Why Not Use DBMS_XMLGEN
151151
• Introduced in ANSI SQL:2003 – Oracle 9iR2
and 10gR2
• Standard functions that can be integrated into
queries
• Removes the need for PL/SQL code to create
XML documents
Standard XML Functions
152152
XMLELEMENT The basic unit for turning column data into
XML fragments
XMLATTRIBUTES Converts column data into attributes of the
parent element
XMLFOREST Allows us to process multiple columns at once
XMLAGG Aggregate separate Fragments into a single
fragment
XMLROOT Allows us to place an XML tag at the start of
our XML document
XML Functions
153153
XMLELEMENT
SELECT XMLELEMENT("name", e.last_name) AS employee
FROM employees e
WHERE e.employee_id = 202;
EMPLOYEE
------------------------------
<name>Fay</name>
154154
XMLELEMENT (2)
SELECT XMLELEMENT("employee",
XMLELEMENT("works_number", e.employee_id),
XMLELEMENT("name", e.last_name)
) AS employee
FROM employees e
WHERE e.employee_id = 202;
EMPLOYEE
----------------------------------------------------------
<employee><works_number>202</works_number><name>Fay</name>
</employee>
155155
XMLATTRIBUTES
SELECT XMLELEMENT("employee",
XMLATTRIBUTES(
e.employee_id AS "works_number",
e.last_name AS "name")
) AS employee
FROM employees e
WHERE e.employee_id = 202;
EMPLOYEE
----------------------------------------------------------
<employee works_number="202" name="Fay"></employee>
156156
XMLFOREST
SELECT XMLELEMENT("employee",
XMLFOREST(
e.employee_id AS "works_number",
e.last_name AS "name",
e.phone_number AS "phone_number")
) AS employee
FROM employees e
WHERE e.employee_id = 202;
EMPLOYEE
----------------------------------------------------------
<employee><works_number>202</works_number><name>Fay</name>
<phone_number>603.123.6666</phone_number></employee>
157157
XMLFOREST Problem
SELECT XMLELEMENT("employee",
XMLFOREST(
e.employee_id AS "works_number",
e.last_name AS "name",
e.phone_number AS "phone_number")
) AS employee
FROM employees e
WHERE e.employee_id in (202, 203);
EMPLOYEE
----------------------------------------------------------
<employee><works_number>202</works_number><name>Fay</name>
<phone_number>603.123.6666</phone_number></employee>
<employee><works_number>203</works_number><name>Mavris</name>
<phone_number>515.123.7777</phone_number></employee>
2 row selected.
158158
XMLAGG
SELECT XMLAGG(
XMLELEMENT("employee",
XMLFOREST(
e.employee_id AS "works_number",
e.last_name AS "name",
e.phone_number AS "phone_number")
)) AS employee
FROM employees e
WHERE e.employee_id in (202, 203);
EMPLOYEE
----------------------------------------------------------
<employee><works_number>202</works_number><name>Fay</name>
<phone_number>603.123.6666</phone_number></employee><employee>
<works_number>203</works_number><name>Mavris</name>
<phone_number>515.123.7777</phone_number></employee>
1 row selected.
159159
• Creating a well formed XML document
XMLROOT
SELECT XMLROOT (
XMLELEMENT("employees",
XMLAGG(
XMLELEMENT("employee",
XMLFOREST(
e.employee_id AS "works_number",
e.last_name AS "name",
e.phone_number AS "phone_number")
))), VERSION '1.0') AS employee
FROM employees e
WHERE e.employee_id in (202, 203);
160160
• Well formed, version bound, beatified XML:
XMLROOT
EMPLOYEE
------------------------------------------
<?xml version="1.0"?>
<employees>
<employee>
<works_number>202</works_number>
<name>Fay</name>
<phone_number>603.123.6666</phone_number>
</employee>
<employee>
<works_number>203</works_number>
<name>Mavris</name>
<phone_number>515.123.7777</phone_number>
</employee>
</employees>
161161
• Using the XQuery language we can create, read
and manipulate XML documents
• Two main functions: XMLQuery and XMLTable
• XQuery is about sequences - XQuery is a
general sequence-manipulation language
• Each sequence can contain numbers, strings,
Booleans, dates, or other XML fragments
Using XQuery
162
Creating XML Document using XQuery
SELECT warehouse_name,
EXTRACTVALUE(warehouse_spec, '/Warehouse/Area'),
XMLQuery(
'for $i in /Warehouse
where $i/Area > 50000
return <Details>
<Docks num="{$i/Docks}"/>
<Rail>
{
if ($i/RailAccess = "Y") then "true" else
"false"
}
</Rail>
</Details>' PASSING warehouse_spec RETURNING CONTENT)
"Big_warehouses"
FROM warehouses;
163
Creating XML Document using XQuery
WAREHOUSE_ID Area Big_warehouses
------------ --------- --------------------------------------------------------
1 25000
2 50000
3 85700 <Details><Docks></Docks><Rail>false</Rail></Details>
4 103000 <Details><Docks num="3"></Docks><Rail>true</Rail></Details>
. . .
164164
Example: Using XMLTable to Read XML
SELECT lines.lineitem, lines.description, lines.partid,
lines.unitprice, lines.quantity
FROM purchaseorder,
XMLTable('for $i in /PurchaseOrder/LineItems/LineItem
where $i/@ItemNumber >= 8
and $i/Part/@UnitPrice > 50
and $i/Part/@Quantity > 2
return $i'
PASSING OBJECT_VALUE
COLUMNS lineitem NUMBER PATH '@ItemNumber',
description VARCHAR2(30) PATH 'Description',
partid NUMBER PATH 'Part/@Id',
unitprice NUMBER PATH 'Part/@UnitPrice',
quantity NUMBER PATH 'Part/@Quantity')
lines;
Oracle 12c JSON Support
165
166166
• Javascript Object Notation
• Converts database tables to a readable
document – just like XML but simplier
• Very common in NoSQL and Big Data solutions
What is JSON
{"FirstName" : "Zohar",
"LastName" : "Elkayam",
"Age" : 36,
"Connection" :
[
{"Type" : “Email", "Value" : "zohar@DBAces.com"},
{"Type" : “Twitter", "Value" : “@realmgic"},
{"Type" : "Site", "Value" : "www.realdbamagic.com"},
]}
167167
• Ability to store data without requiring a Schema
– Store semi-structured data in its native (aggregated)
form
• Ability to query data without knowledge of
Schema
• Ability to index data with knowledge of Schema
JSON Benefits
168168
• Oracle supports JSON since version 12.1.0.2
• JSON documents stored in the database using
existing data types: VARCHAR2, CLOB or BLOB
• External JSON data sources accessible through
external tables including HDFS
• Data accessible via REST API
Oracle JSON Support
169169
• Simple well understood model
• CRUD operations are mapped to HTTP Verbs
– Create / Update : PUT / POST
– Retrieve : GET
– Delete : DELETE
– QBE, Bulk Update, Utilitiy functions : POST
• Stateless
REST based API for JSON documents
170170
• Similar role to XPATH in XML
• Syntactically similar to Java Script (. and [ ])
• Compatible with Java Script
JSON Path Expression
171171
• There are few common JSON Operators:
Common JSON SQL Functions
JSON_EXISTS Checks if a value exists in the JSON
JSON_VALUE Retrieve a scalar value from JSON
JSON_QUERY Query a string from JSON Document
JSON_TABLE Query data from JSON Document (like
XMLTable)
172172
• Extract JSON fragment from JSON document
JSON_QUERY
select count(*)
from J_PURCHASEORDER
where JSON_EXISTS(
PO_DOCUMENT, '$.ShippingInstructions.Address.state‘)
/
173173
• Generate rows from a JSON Array
• Pivot properties / key values into columns
• Use Nested Path clause to process multi-level
collections with a single JSON_TABLE operator.
Using JSON_TABLE
174174
• 1 Row of output for each row in table
Example: JSON_TABLE
select M.*
from J_PURCHASEORDER p,
JSON_TABLE(
p.PO_DOCUMENT,
'$'
columns
PO_NUMBER NUMBER(10) path '$.PONumber',
REFERENCE VARCHAR2(30 CHAR) path '$.Reference',
REQUESTOR VARCHAR2(32 CHAR) path '$.Requestor',
USERID VARCHAR2(10 CHAR) path '$.User',
COSTCENTER VARCHAR2(16) path '$.CostCenter'
) M
where PO_NUMBER > 1600 and PO_Number < 1605
/
175175
• 1 row output for each member of LineItems array ``
Example: JSON_TABLE (2)
select D.*
from J_PURCHASEORDER p,
JSON_TABLE(
p.PO_DOCUMENT,
'$'
columns(
PO_NUMBER NUMBER(10) path '$.PONumber',
NESTED PATH '$.LineItems[*]'
columns(
ITEMNO NUMBER(16) path '$.ItemNumber',
UPCCODE VARCHAR2(14 CHAR) path '$.Part.UPCCode‘ ))
) D
where PO_NUMBER = 1600 or PO_NUMBER = 1601
/
176176
• Known Query Patterns : JSON Path expression
– Functional indexes using JSON_VALUE and,
JSON_EXISTS
– Materialized View using JSON_TABLE()
• Ad-hoc Query Strategy
– Based on Oracle’s full text index (Oracle Text)
– Support ad-hoc path, value and keyword query
search using JSON Path expressions
JSON Indexing
Regular Expression
177
178178
• Regular expression (regexp) is a sequence of
characters that define a search pattern
• Commonly used for smart “Search and
Replace” of patterns and for input validations
of text
• Widely introduced in Oracle 10g (and it even
existed even before that)
Regular Expression
179179
Common REGEXP
Functions and Operators
REGEXP_LIKE Perform regular expression matching
REGEXP_REPLACE Extends the functionality of the REPLACE
function by using patterns
REGEXP_SUBSTR Extends the functionality of the SUBSTR
function by using patterns
REGEXP_COUNT Count the number of matches of the
pattern in a given string
REGEXP_INSTR Extends the functionality of the INSTR
function by using patterns
180180180180
• Concatenation: No operator between elements.
• Quantifiers:
– . Matches any character in the database character set
– * 0 or more matches
– + 1 or more matches
– ? 0 or 1 match
– {n} Exactly n matches
– {n,} n or more matches
– {n, m} Between n and m (inclusive) matches
– {, m} Between 0 an m (inclusive) matches
• Alternation: [|]
• Grouping: ()
Supported Regular Expression Patterns
181181
Supported Regular Expression Patterns
Value Description
^
Matches the beginning of a string. If used with
a match_parameter of 'm', it matches the start of a line
anywhere within expression.
$
Matches the end of a string. If used with
a match_parameter of 'm', it matches the end of a line
anywhere withinexpression.
W Matches a nonword character.
s Matches a whitespace character.
S matches a non-whitespace character.
A
Matches the beginning of a string or matches at the end of
a string before a newline character.
Z Matches at the end of a string.
182182
Character Class Description
[:alnum:] Alphanumeric characters
[:alpha:] Alphabetic characters
[:blank:] Blank Space Characters
[:cntrl:] Control characters (nonprinting)
[:digit:] Numeric digits
[:graph:] Any [:punct:], [:upper:], [:lower:], and [:digit:] chars
[:lower:] Lowercase alphabetic characters
[:print:] Printable characters
[:punct:] Punctuation characters
[:space:]
Space characters (nonprinting), such as carriage return,
newline, vertical tab, and form feed
[:upper:] Uppercase alphabetic characters
[:xdigit:] Hexidecimal characters
Character Classes
Regular Expression Demo
183
184184
• Regular expressions might be slow when used
on large amount of data
• Writing regular expression can be very tricky –
make sure your pattern is correct
• Oracle REGEXP syntax is not standard, regular
expression might not work or partially work
causing wrong results
• There can only be up to 9 placeholders in a
given quantifier
Pitfalls
SQLcl Introduction
The Next Generation of SQL*Plus?
185
186186
• Introduced in Oracle 5 (1985)
• Looks very simple but has tight integration with
other Oracle infrastructure and tools
• Very good for reporting, scripting, and
automation
• Replaced old CLI tool called …
UFI (“User Friendly Interface”)
SQL*Plus
187187
• Nothing really wrong with SQL*Plus – it is being
updated constantly but it is missing a lot of
functionality
• SQL*Plus forces us to use GUI tools to complete
some basic tasks
• Easy to understand, a bit hard to use
• Not easy for new users or developers
What’s Wrong With SQL*Plus?
188188
• SQLcl is a new command line interface (CLI) for SQL
users and DBAs
• It is part of the SQL Developer suite – developed by the
same team: Oracle Database Development Tools Team
• Can do most of what SQL*Plus does and much more
• Minimal installation, minimal requirements
Introducing SQLcl
189189
• It’s still in the early adopter version (current
version: 4.2.0.15.295.1605 RC, October 23,
2015)
• Uses Java, one version for Windows, Linux and
OS X
• Planned to be shipped out with Oracle
Database 12cR2 (“within the next 12 month”)
Introducing SQLcl (cont.)
190190
• Early Adopter version/RC
• QA still logging bugs from SQL*Plus regression tests
• Adding support for existing SQL*Plus commands and
syntax
• Adding new commands
• But can it do...?
– Yes
– Not yet
– No
Current Status
191191
• Download from: SQL Developer Download
page
• Unzip the file
• Run it
Installing
What Can It Do?
192
193193
• Use the tab key to complete commands
• Can be used to list tables, views or other queriable
objects
• Can be used to replace the * with actual column names
• Use the arrow keys to move around the command
• Use CTRL+W and CTRL+S to jump to the beginning/end
of commands
Object Completion and Easy Edit
194194
• 100 command history buffer
• Commands are persistent between sessions (watch out for
security!)
• Use UP and DOWN arrow keys to access old commands
• Usage:
history
history usage
History script
history full
History clear [session?]
• Load from history into command buffer:
history <number>
Command History
195195
• Describe lists the column of the tables just like SQL*Plus
• Information shows column names, default values, indexes
and constraints.
• In 12c database information shows table statistics and In
memory status
• Works for table, views, sequences, and code objects
• Info+ shows additional information regarding column
statistics and column histograms
Describe, Information and info+
196196
• Outputting query results becomes easier with the
“set sqlformat” command (also available in SQL
Developer)
• We can create a query in the “regular” way and
then switch between the different output styles:
– ANSIConsole
– Fixed column size output
– XML or JSON output
– HTML output generates a built in search field and a responsive html output for
the result only
Generating Pretty Output
197197
• We can generate loader ready output (with “|” as a
delimiter)
• We can generate insert commands
• We can easily generate CSV output
• Usage:
set sqlformat {
csv,html,xml,json,ansiconsole,insert,
loader,fixed,default}
Generating Other Useful Outputs
198198
• Loads a comma separated value (csv) file into
a table
• The first row of the file must be a header row
and the file must be encoded UTF8
• The load is processed with 50 rows per batch
• Usage:
LOAD [schema.]table_name[@db_link] file_name
Load Data From CSV File
199199
• There is a lot in SQL than meets the eye
• Wise use of analytic queries can be good for
readability and performance
• Recursive queries are good replacement for the
old connect by prior but a little dangerous
• Oracle 12c features are really cool!
• Look out for SQLcl: it’s cool and it’s going places!
Summary
200200
• The Model clause
• Using the WITH clause
• Adding PL/SQL to our SQL (Oracle 12c)
• Hints and other tuning considerations
• The SQL reference book is 1906 pages long.
We didn’t talk about most of it…
What Did We Not Talk About?
Q&A
Any Questions? Now will be the time!
201
202202
Zohar Elkayam
twitter: @realmgic
Zohar@Brillix.co.il
www.ilDBA.co.il
www.realdbamagic.com
203203203203

More Related Content

What's hot (20)

PPTX
SQL Plan Directives explained
Mauro Pagano
 
PDF
Average Active Sessions RMOUG2007
John Beresniewicz
 
PDF
DOAG - Oracle Database Locking Mechanism Demystified
Pini Dibask
 
PDF
DB2 TABLESPACES
Rahul Anand
 
PDF
Oracle Performance Tuning Fundamentals
Enkitec
 
PPT
Adop and maintenance task presentation 151015
andreas kuncoro
 
PPTX
Oracle Database Performance Tuning Basics
nitin anjankar
 
PPTX
JSON and the Oracle Database
Maria Colgan
 
PDF
Awr + 12c performance tuning
AiougVizagChapter
 
PDF
MySQL Performance Schema in Action: the Complete Tutorial
Sveta Smirnova
 
PPTX
Oracle AWR Data mining
Yury Velikanov
 
PDF
Oracle Database SQL Tuning Concept
Chien Chung Shen
 
PDF
New Generation Oracle RAC Performance
Anil Nair
 
PDF
Editioning use in ebs
aioughydchapter
 
PPT
Sql Server Basics
rainynovember12
 
PPTX
Understanding How is that Adaptive Cursor Sharing (ACS) produces multiple Opt...
Carlos Sierra
 
PPTX
Top 10 tips for Oracle performance (Updated April 2015)
Guy Harrison
 
PDF
PostgreSQL Materialized Views with Active Record
David Roberts
 
PDF
Hash joins and bloom filters at AMIS25
Getting value from IoT, Integration and Data Analytics
 
SQL Plan Directives explained
Mauro Pagano
 
Average Active Sessions RMOUG2007
John Beresniewicz
 
DOAG - Oracle Database Locking Mechanism Demystified
Pini Dibask
 
DB2 TABLESPACES
Rahul Anand
 
Oracle Performance Tuning Fundamentals
Enkitec
 
Adop and maintenance task presentation 151015
andreas kuncoro
 
Oracle Database Performance Tuning Basics
nitin anjankar
 
JSON and the Oracle Database
Maria Colgan
 
Awr + 12c performance tuning
AiougVizagChapter
 
MySQL Performance Schema in Action: the Complete Tutorial
Sveta Smirnova
 
Oracle AWR Data mining
Yury Velikanov
 
Oracle Database SQL Tuning Concept
Chien Chung Shen
 
New Generation Oracle RAC Performance
Anil Nair
 
Editioning use in ebs
aioughydchapter
 
Sql Server Basics
rainynovember12
 
Understanding How is that Adaptive Cursor Sharing (ACS) produces multiple Opt...
Carlos Sierra
 
Top 10 tips for Oracle performance (Updated April 2015)
Guy Harrison
 
PostgreSQL Materialized Views with Active Record
David Roberts
 
Hash joins and bloom filters at AMIS25
Getting value from IoT, Integration and Data Analytics
 

Viewers also liked (20)

PPTX
Exploring Advanced SQL Techniques Using Analytic Functions
Zohar Elkayam
 
PDF
Advanced PL/SQL Optimizing for Better Performance 2016
Zohar Elkayam
 
PPT
Oracle training-institutes-in-hyderabad
Kelly Technologies
 
PDF
Magic With Oracle - Presentation
Francisco Alvarez
 
PDF
Adding real time reporting to your database oracle db in memory
Zohar Elkayam
 
PPTX
Sql server scalability fundamentals
Chris Adkin
 
PPT
10g plsql slide
Tanu_Manu
 
PPTX
Exploring Advanced SQL Techniques Using Analytic Functions
Zohar Elkayam
 
PPT
Plsql
Mandeep Singh
 
PDF
Things Every Oracle DBA Needs To Know About The Hadoop Ecosystem
Zohar Elkayam
 
PDF
Oracle Data Guard A to Z
Zohar Elkayam
 
PDF
ORACLE, SQL, PL/SQL Made very very Easy Happy Learning....
Racharla Rohit Varma
 
PDF
OOW2016: Exploring Advanced SQL Techniques Using Analytic Functions
Zohar Elkayam
 
PDF
Understanding oracle rac internals part 2 - slides
Mohamed Farouk
 
PPT
PL/SQL
Vaibhav0
 
PDF
Oracle Database Advanced Querying (2016)
Zohar Elkayam
 
PDF
Oracle RAC Internals - The Cache Fusion Edition
Markus Michalewicz
 
PDF
Understanding oracle rac internals part 1 - slides
Mohamed Farouk
 
PDF
Understanding Oracle RAC 11g Release 2 Internals
Markus Michalewicz
 
DOC
Sql queries
narendrababuc
 
Exploring Advanced SQL Techniques Using Analytic Functions
Zohar Elkayam
 
Advanced PL/SQL Optimizing for Better Performance 2016
Zohar Elkayam
 
Oracle training-institutes-in-hyderabad
Kelly Technologies
 
Magic With Oracle - Presentation
Francisco Alvarez
 
Adding real time reporting to your database oracle db in memory
Zohar Elkayam
 
Sql server scalability fundamentals
Chris Adkin
 
10g plsql slide
Tanu_Manu
 
Exploring Advanced SQL Techniques Using Analytic Functions
Zohar Elkayam
 
Things Every Oracle DBA Needs To Know About The Hadoop Ecosystem
Zohar Elkayam
 
Oracle Data Guard A to Z
Zohar Elkayam
 
ORACLE, SQL, PL/SQL Made very very Easy Happy Learning....
Racharla Rohit Varma
 
OOW2016: Exploring Advanced SQL Techniques Using Analytic Functions
Zohar Elkayam
 
Understanding oracle rac internals part 2 - slides
Mohamed Farouk
 
PL/SQL
Vaibhav0
 
Oracle Database Advanced Querying (2016)
Zohar Elkayam
 
Oracle RAC Internals - The Cache Fusion Edition
Markus Michalewicz
 
Understanding oracle rac internals part 1 - slides
Mohamed Farouk
 
Understanding Oracle RAC 11g Release 2 Internals
Markus Michalewicz
 
Sql queries
narendrababuc
 
Ad

Similar to Oracle Database Advanced Querying (20)

PDF
The art of querying – newest and advanced SQL techniques
Zohar Elkayam
 
PDF
Oracle Advanced SQL and Analytic Functions
Zohar Elkayam
 
PPT
Les04
Sudharsan S
 
PPT
Les17
Vijay Kumar
 
PPT
e computer notes - Enhancements to the group by clause
ecomputernotes
 
PPTX
SQL Optimizer vs Hive
Vishaka Balasubramanian Sekar
 
PDF
Consultas con agrupaci¾n de datos
Caleb Gutiérrez
 
ODP
SQL Tunning
Dhananjay Goel
 
PPTX
Oracle: Functions
oracle content
 
PPTX
Oracle: Functions
DataminingTools Inc
 
PPT
Chapter5.ppt
YashaswiniSrinivasan1
 
PPT
Les04- Reporting Aggregated Data Using the Group Functions.ppt
iam529946
 
PPTX
Sql and PL/SQL Best Practices I
Carlos Oliveira
 
PPT
Creating other schema objects
Syed Zaid Irshad
 
PPTX
MySQL 8 -- A new beginning : Sunshine PHP/PHP UK (updated)
Dave Stokes
 
PPT
PHP mysql Aggregate functions
Mudasir Syed
 
PPT
Aggregating Data Using Group Functions
Salman Memon
 
PPTX
Simplifying SQL with CTE's and windowing functions
Clayton Groom
 
The art of querying – newest and advanced SQL techniques
Zohar Elkayam
 
Oracle Advanced SQL and Analytic Functions
Zohar Elkayam
 
e computer notes - Enhancements to the group by clause
ecomputernotes
 
SQL Optimizer vs Hive
Vishaka Balasubramanian Sekar
 
Consultas con agrupaci¾n de datos
Caleb Gutiérrez
 
SQL Tunning
Dhananjay Goel
 
Oracle: Functions
oracle content
 
Oracle: Functions
DataminingTools Inc
 
Chapter5.ppt
YashaswiniSrinivasan1
 
Les04- Reporting Aggregated Data Using the Group Functions.ppt
iam529946
 
Sql and PL/SQL Best Practices I
Carlos Oliveira
 
Creating other schema objects
Syed Zaid Irshad
 
MySQL 8 -- A new beginning : Sunshine PHP/PHP UK (updated)
Dave Stokes
 
PHP mysql Aggregate functions
Mudasir Syed
 
Aggregating Data Using Group Functions
Salman Memon
 
Simplifying SQL with CTE's and windowing functions
Clayton Groom
 
Ad

More from Zohar Elkayam (19)

PDF
Docker Concepts for Oracle/MySQL DBAs and DevOps
Zohar Elkayam
 
PDF
Oracle Database Performance Tuning Advanced Features and Best Practices for DBAs
Zohar Elkayam
 
PDF
PL/SQL New and Advanced Features for Extreme Performance
Zohar Elkayam
 
PDF
Things Every Oracle DBA Needs to Know About the Hadoop Ecosystem 20170527
Zohar Elkayam
 
PDF
Things Every Oracle DBA Needs to Know About the Hadoop Ecosystem (c17lv version)
Zohar Elkayam
 
PDF
Oracle 12c New Features For Better Performance
Zohar Elkayam
 
PPTX
Introduction to Oracle Data Guard Broker
Zohar Elkayam
 
PDF
Exploring Oracle Multitenant in Oracle Database 12c
Zohar Elkayam
 
PDF
Rapid Cluster Computing with Apache Spark 2016
Zohar Elkayam
 
PPTX
MySQL 5.7 New Features for Developers
Zohar Elkayam
 
PPTX
Is SQLcl the Next Generation of SQL*Plus?
Zohar Elkayam
 
PDF
Things Every Oracle DBA Needs to Know about the Hadoop Ecosystem
Zohar Elkayam
 
PDF
Advanced PLSQL Optimizing for Better Performance
Zohar Elkayam
 
PDF
The Hadoop Ecosystem for Developers
Zohar Elkayam
 
PDF
Big data for cio 2015
Zohar Elkayam
 
PDF
SQLcl the next generation of SQLPlus?
Zohar Elkayam
 
PDF
Intro to Big Data
Zohar Elkayam
 
PDF
Oracle Data Guard Broker Webinar
Zohar Elkayam
 
PDF
Oracle Database In-Memory Option for ILOUG
Zohar Elkayam
 
Docker Concepts for Oracle/MySQL DBAs and DevOps
Zohar Elkayam
 
Oracle Database Performance Tuning Advanced Features and Best Practices for DBAs
Zohar Elkayam
 
PL/SQL New and Advanced Features for Extreme Performance
Zohar Elkayam
 
Things Every Oracle DBA Needs to Know About the Hadoop Ecosystem 20170527
Zohar Elkayam
 
Things Every Oracle DBA Needs to Know About the Hadoop Ecosystem (c17lv version)
Zohar Elkayam
 
Oracle 12c New Features For Better Performance
Zohar Elkayam
 
Introduction to Oracle Data Guard Broker
Zohar Elkayam
 
Exploring Oracle Multitenant in Oracle Database 12c
Zohar Elkayam
 
Rapid Cluster Computing with Apache Spark 2016
Zohar Elkayam
 
MySQL 5.7 New Features for Developers
Zohar Elkayam
 
Is SQLcl the Next Generation of SQL*Plus?
Zohar Elkayam
 
Things Every Oracle DBA Needs to Know about the Hadoop Ecosystem
Zohar Elkayam
 
Advanced PLSQL Optimizing for Better Performance
Zohar Elkayam
 
The Hadoop Ecosystem for Developers
Zohar Elkayam
 
Big data for cio 2015
Zohar Elkayam
 
SQLcl the next generation of SQLPlus?
Zohar Elkayam
 
Intro to Big Data
Zohar Elkayam
 
Oracle Data Guard Broker Webinar
Zohar Elkayam
 
Oracle Database In-Memory Option for ILOUG
Zohar Elkayam
 

Recently uploaded (20)

PDF
Future-Proof or Fall Behind? 10 Tech Trends You Can’t Afford to Ignore in 2025
DIGITALCONFEX
 
PDF
“Voice Interfaces on a Budget: Building Real-time Speech Recognition on Low-c...
Edge AI and Vision Alliance
 
PPTX
Q2 FY26 Tableau User Group Leader Quarterly Call
lward7
 
PPTX
Agentforce World Tour Toronto '25 - Supercharge MuleSoft Development with Mod...
Alexandra N. Martinez
 
PDF
What’s my job again? Slides from Mark Simos talk at 2025 Tampa BSides
Mark Simos
 
PDF
The 2025 InfraRed Report - Redpoint Ventures
Razin Mustafiz
 
PDF
Newgen Beyond Frankenstein_Build vs Buy_Digital_version.pdf
darshakparmar
 
PDF
LOOPS in C Programming Language - Technology
RishabhDwivedi43
 
PDF
UPDF - AI PDF Editor & Converter Key Features
DealFuel
 
PDF
Book industry state of the nation 2025 - Tech Forum 2025
BookNet Canada
 
PDF
Staying Human in a Machine- Accelerated World
Catalin Jora
 
PDF
Reverse Engineering of Security Products: Developing an Advanced Microsoft De...
nwbxhhcyjv
 
PPTX
Agentforce World Tour Toronto '25 - MCP with MuleSoft
Alexandra N. Martinez
 
PDF
Newgen 2022-Forrester Newgen TEI_13 05 2022-The-Total-Economic-Impact-Newgen-...
darshakparmar
 
PDF
UiPath DevConnect 2025: Agentic Automation Community User Group Meeting
DianaGray10
 
DOCX
Python coding for beginners !! Start now!#
Rajni Bhardwaj Grover
 
PDF
“Computer Vision at Sea: Automated Fish Tracking for Sustainable Fishing,” a ...
Edge AI and Vision Alliance
 
DOCX
Cryptography Quiz: test your knowledge of this important security concept.
Rajni Bhardwaj Grover
 
PDF
AI Agents in the Cloud: The Rise of Agentic Cloud Architecture
Lilly Gracia
 
PDF
“NPU IP Hardware Shaped Through Software and Use-case Analysis,” a Presentati...
Edge AI and Vision Alliance
 
Future-Proof or Fall Behind? 10 Tech Trends You Can’t Afford to Ignore in 2025
DIGITALCONFEX
 
“Voice Interfaces on a Budget: Building Real-time Speech Recognition on Low-c...
Edge AI and Vision Alliance
 
Q2 FY26 Tableau User Group Leader Quarterly Call
lward7
 
Agentforce World Tour Toronto '25 - Supercharge MuleSoft Development with Mod...
Alexandra N. Martinez
 
What’s my job again? Slides from Mark Simos talk at 2025 Tampa BSides
Mark Simos
 
The 2025 InfraRed Report - Redpoint Ventures
Razin Mustafiz
 
Newgen Beyond Frankenstein_Build vs Buy_Digital_version.pdf
darshakparmar
 
LOOPS in C Programming Language - Technology
RishabhDwivedi43
 
UPDF - AI PDF Editor & Converter Key Features
DealFuel
 
Book industry state of the nation 2025 - Tech Forum 2025
BookNet Canada
 
Staying Human in a Machine- Accelerated World
Catalin Jora
 
Reverse Engineering of Security Products: Developing an Advanced Microsoft De...
nwbxhhcyjv
 
Agentforce World Tour Toronto '25 - MCP with MuleSoft
Alexandra N. Martinez
 
Newgen 2022-Forrester Newgen TEI_13 05 2022-The-Total-Economic-Impact-Newgen-...
darshakparmar
 
UiPath DevConnect 2025: Agentic Automation Community User Group Meeting
DianaGray10
 
Python coding for beginners !! Start now!#
Rajni Bhardwaj Grover
 
“Computer Vision at Sea: Automated Fish Tracking for Sustainable Fishing,” a ...
Edge AI and Vision Alliance
 
Cryptography Quiz: test your knowledge of this important security concept.
Rajni Bhardwaj Grover
 
AI Agents in the Cloud: The Rise of Agentic Cloud Architecture
Lilly Gracia
 
“NPU IP Hardware Shaped Through Software and Use-case Analysis,” a Presentati...
Edge AI and Vision Alliance
 

Oracle Database Advanced Querying

  • 1. 1 Oracle Database Advanced Querying 111 Zohar Elkayam CTO, Brillix [email protected] www.realdbamagic.com Twitter: @realmgic
  • 2. 22 • Zohar Elkayam, CTO/COO at Brillix-DBAces • Oracle ACE Associate • DBA, team leader, Oracle University instructor, public speaker, and a senior consultant for over 18 years • Editor of ilDBA – Israel Database Community website • Blogger – www.realdbamagic.com Who am I?
  • 3. 3 We are committed to provide the highest quality of services delivered by our dedicated team of highly trained and experienced industry’s top data experts. We offer:  Complete integrated end-to-end solutions based on best-of- breed innovations in database, security and big data technologies  On-site professional customized trainings led by our team of Oracle ACEs and Oracle Certified Professionals  Comprehensive security solutions and services for leading database platforms and business applications, leveraging a world-class team of security experts About Brillix
  • 4. 44 • Aggregative and advanced grouping options • Analytic functions, ranking and pagination • Hierarchical and recursive queries • Oracle 12c new rows pattern matching feature • XML and JSON handling with SQL • Regular Expressions • SQLcl – a new replacement tool for SQL*Plus from Oracle Agenda
  • 5. 55 •‫הספר‬"Oracle SQL–‫יכולות‬ ‫מתקדמות‬,‫לשולף‬ ‫מדריך‬ ‫המהיר‬"‫ב‬ ‫פורסם‬-2011 •‫ה‬ ‫ספר‬ ‫זה‬-SQL‫הראשון‬ ‫בעברית‬ ‫שנכתב‬ ‫והיחיד‬ ‫סופו‬ ‫ועד‬ ‫מתחילתו‬ •‫עמיאל‬ ‫ידי‬ ‫על‬ ‫נכתב‬ ‫הספר‬ ‫שלי‬ ‫טכנית‬ ‫עריכה‬ ‫ועבר‬ ‫דיוויס‬ ‫אודות‬Oracle SQL–‫מתקדמות‬ ‫יכולות‬
  • 6. 6 The REAL Agenda 10:30-10:45‫הפסקה‬ 12:30-13:30‫משתתפ‬ ‫לכל‬ ‫צהריים‬ ‫ארוחת‬‫הכנס‬ ‫י‬ 15:00-15:15‫מתוקה‬ ‫הפסקה‬ 16:30‫הביתה‬ ‫הולכים‬
  • 7. 77 • SQL was invented in 1970 by Dr. E. F. Codd • Each vendor had its own flavor of SQL • Standardized by ASNI since 1986 • Current stable standard is ANSI SQL:2011/2008 • Oracle 12c is fully compliant to CORE SQL:2011 • Oracle 11g is compliant to SQL:2008 ANSI SQL
  • 8. 88 • In this seminar we will only talk about Queries Queries
  • 9. Group Functions More than just group by… 9
  • 10. 10 • Using SQL for aggregation: – Group functions basics – The CUBE and ROLLUP extensions to the GROUP BY clause – The GROUPING functions – The GROUPING SETS expression • Working with composite columns • Using concatenated groupings Group Function and SQL
  • 11. 1111 • Group functions will return a single row for each group • The group by clause groups rows together and allows group functions to be applied • Common group functions: SUM, MIN, MAX, AVG, etc. Basics
  • 12. 12 Group Functions Syntax SELECT [column,] group_function(column). . . FROM table [WHERE condition] [GROUP BY group_by_expression] [ORDER BY column]; SELECT AVG(salary), STDDEV(salary), COUNT(commission_pct),MAX(hire_date) FROM hr.employees WHERE job_id LIKE 'SA%';
  • 13. 13 SELECT department_id, job_id, SUM(salary), COUNT(employee_id) FROM hr.employees GROUP BY department_id, job_id Order by department_id; The GROUP BY Clause SELECT [column,] group_function(column) FROM table [WHERE condition] [GROUP BY group_by_expression] [ORDER BY column];
  • 14. 14 • Use the HAVING clause to specify which groups are to be displayed • You further restrict the groups on the basis of a limiting condition The HAVING Clause SELECT [column,] group_function(column)... FROM table [WHERE condition] [GROUP BY group_by_expression] [HAVING having_expression] [ORDER BY column];
  • 15. 15 • Use ROLLUP or CUBE with GROUP BY to produce superaggregate rows by cross- referencing columns • ROLLUP grouping produces a result set containing the regular grouped rows and the subtotal and grand total values • CUBE grouping produces a result set containing the rows from ROLLUP and cross- tabulation rows GROUP BY with the ROLLUP and CUBE Operators
  • 16. 16 • ROLLUP is an extension of the GROUP BY clause • Use the ROLLUP operation to produce cumulative aggregates, such as subtotals Using the ROLLUP Operator SELECT [column,] group_function(column). . . FROM table [WHERE condition] [GROUP BY [ROLLUP] group_by_expression] [HAVING having_expression]; [ORDER BY column];
  • 17. 17 Using the ROLLUP Operator: Example SELECT department_id, job_id, SUM(salary) FROM hr.employees WHERE department_id < 60 GROUP BY ROLLUP(department_id, job_id); 1 2 3 Total by DEPARTMENT_ID and JOB_ID Total by DEPARTMENT_ID Grand total
  • 18. 18 • CUBE is an extension of the GROUP BY clause • You can use the CUBE operator to produce cross-tabulation values with a single SELECT statement Using the CUBE Operator SELECT [column,] group_function(column)... FROM table [WHERE condition] [GROUP BY [CUBE] group_by_expression] [HAVING having_expression] [ORDER BY column];
  • 19. 19 1 2 3 4 Grand total Total by JOB_ID Total by DEPARTMENT_ID and JOB_ID Total by DEPARTMENT_ID SELECT department_id, job_id, SUM(salary) FROM hr.employees WHERE department_id < 60 GROUP BY CUBE (department_id, job_id); . . . Using the CUBE Operator: Example
  • 20. 20 SELECT [column,] group_function(column) .. , GROUPING(expr) FROM table [WHERE condition] [GROUP BY [ROLLUP][CUBE] group_by_expression] [HAVING having_expression] [ORDER BY column]; • The GROUPING function: – Is used with the CUBE or ROLLUP operator – Is used to find the groups forming the subtotal in a row – Is used to differentiate stored NULL values from NULL values created by ROLLUP or CUBE – Returns 0 or 1 Working with the GROUPING Function
  • 21. 21 SELECT department_id DEPTID, job_id JOB, SUM(salary), GROUPING(department_id) GRP_DEPT, GROUPING(job_id) GRP_JOB FROM hr.employees WHERE department_id < 50 GROUP BY ROLLUP(department_id, job_id); Working with the GROUPING Function: Example 1 2 3
  • 22. 2222 • Extension to the GROUPING function • GROUPING_ID returns a number corresponding to the GROUPING bit vector associated with a row • Useful for understanding what level the row is aggregated at and filtering those rows Working with GROUPING_ID Function
  • 23. 2323 GROUPING_ID Function Example SELECT department_id DEPTID, job_id JOB, SUM(salary), GROUPING_ID(department_id,job_id) GRP_ID FROM hr.employees WHERE department_id < 40 GROUP BY CUBE(department_id, job_id); DEPTID JOB SUM(SALARY) GRP_ID ---------- ---------- ----------- ---------- 48300 3 MK_MAN 13000 2 MK_REP 6000 2 PU_MAN 11000 2 AD_ASST 4400 2 PU_CLERK 13900 2 10 4400 1 10 AD_ASST 4400 0 20 19000 1 20 MK_MAN 13000 0 20 MK_REP 6000 0 30 24900 1 30 PU_MAN 11000 0 30 PU_CLERK 13900 0
  • 24. 2424 • GROUP_ID distinguishes duplicate groups resulting from a GROUP BY specification • A Unique group will be assigned 0, the non unique will be assigned 1 to n-1 for n duplicate groups • Useful in filtering out duplicate groupings from the query result Working with GROUP_ID Function
  • 25. 2525 GROUP_ID Function Example SELECT department_id DEPTID, job_id JOB, SUM(salary), GROUP_ID() UNIQ_GRP_ID FROM hr.employees WHERE department_id < 40 GROUP BY department_id, CUBE(department_id, job_id); DEPTID JOB SUM(SALARY) UNIQ_GRP_ID ---------- ---------- ----------- ----------- 10 AD_ASST 4400 0 20 MK_MAN 13000 0 20 MK_REP 6000 0 30 PU_MAN 11000 0 30 PU_CLERK 13900 0 10 AD_ASST 4400 1 20 MK_MAN 13000 1 20 MK_REP 6000 1 30 PU_MAN 11000 1 30 PU_CLERK 13900 1 10 4400 0 20 19000 0 30 24900 0 10 4400 1 20 19000 1 30 24900 1
  • 26. 26 • The GROUPING SETS syntax is used to define multiple groupings in the same query. • All groupings specified in the GROUPING SETS clause are computed and the results of individual groupings are combined with a UNION ALL operation. • Grouping set efficiency: – Only one pass over the base table is required. – There is no need to write complex UNION statements. – The more elements GROUPING SETS has, the greater the performance benefit. GROUPING SETS
  • 27. 28 SELECT department_id, job_id, manager_id, AVG(salary) FROM hr.employees GROUP BY GROUPING SETS ((department_id,job_id), (job_id,manager_id)); GROUPING SETS: Example . . . . . . 1 2
  • 28. 30 • A composite column is a collection of columns that are treated as a unit. ROLLUP (a,(b,c), d) • Use parentheses within the GROUP BY clause to group columns, so that they are treated as a unit while computing ROLLUP or CUBE operators. • When used with ROLLUP or CUBE, composite columns require skipping aggregation across certain levels. Composite Columns
  • 29. 32 SELECT department_id, job_id, manager_id, SUM(salary) FROM hr.employees GROUP BY ROLLUP( department_id,(job_id, manager_id)); Composite Columns: Example … 1 2 3 4
  • 30. 34 • Concatenated groupings offer a concise way to generate useful combinations of groupings. • To specify concatenated grouping sets, you separate multiple grouping sets, ROLLUP, and CUBE operations with commas so that the Oracle server combines them into a single GROUP BY clause. • The result is a cross-product of groupings from each GROUPING SET. Concatenated Groupings GROUP BY GROUPING SETS(a, b), GROUPING SETS(c, d)
  • 31. 35 SELECT department_id, job_id, manager_id, SUM(salary) FROM hr.employees GROUP BY department_id, ROLLUP(job_id), CUBE(manager_id); Concatenated Groupings: Example … … … 1 3 4 5 6 2 7 … …
  • 32. Pivot and Unpivot Turning things around! 36
  • 33. PIVOT and UNPIVOT Clauses of the SELECT Statement • You can use the PIVOT operator of the SELECT statement to write cross-tabulation queries that rotate the column values into new columns, aggregating data in the process. • You can use the UNPIVOT operator of the SELECT statement to rotate columns into values of a column. PIVOT UNPIVOT
  • 34. 38 Pivoting on the QUARTER Column: Conceptual Example 30,000 40,000 60,000 30,000 40,000 20,000 AMOUNT_ SOLD 2,500Q1IUSAKids Jeans 2,000Q2CJapanKids Jeans 2,000Q3SUSAShorts I P C CHANNEL Kids Jeans Shorts Shorts PRODUCT 1,000Q2Germany 1,500Q4USA Q2 QUARTER 2,500Poland QUANTITY_ SOLD COUNTRY 2,000 Q3 Kids Jeans Shorts PRODUCT 3,500 2,000 Q2 1,5002,500 Q4Q1
  • 35. 3939 • Pivoting the data before 11g was a complex query which required the use of the CASE or DECODE functions Pivoting Before Oracle 11g select product, sum(case when quarter = 'Q1' then amount_sold else null end) Q1, sum(case when quarter = 'Q2' then amount_sold else null end) Q2, sum(case when quarter = 'Q3' then amount_sold else null end) Q3, sum(case when quarter = 'Q4' then amount_sold else null end) Q4 from sales group by product;
  • 36. 40 Pivot Clause Syntax table_reference PIVOT [ XML ] ( aggregate_function ( expr ) [[AS] alias ] [, aggregate_function ( expr ) [[AS] alias ] ]... pivot_for_clause pivot_in_clause ) -- Specify the column(s) to pivot whose values are to -- be pivoted into columns. pivot_for_clause = FOR { column |( column [, column]... ) } -- Specify the pivot column values from the columns you -- specified in the pivot_for_clause. pivot_in_clause = IN ( { { { expr | ( expr [, expr]... ) } [ [ AS] alias] }... | subquery | { ANY | ANY [, ANY]...} } )
  • 37. 42 Creating a New View: Example CREATE OR REPLACE VIEW sales_view AS SELECT prod_name AS product, country_name AS country, channel_id AS channel, SUBSTR(calendar_quarter_desc, 6,2) AS quarter, SUM(amount_sold) AS amount_sold, SUM(quantity_sold) AS quantity_sold FROM sales, times, customers, countries, products WHERE sales.time_id = times.time_id AND sales.prod_id = products.prod_id AND sales.cust_id = customers.cust_id AND customers.country_id = countries.country_id GROUP BY prod_name, country_name, channel_id, SUBSTR(calendar_quarter_desc, 6, 2);
  • 38. 44 Selecting the SALES VIEW Data SELECT product, country, channel, quarter, quantity_sold FROM sales_view; PRODUCT COUNTRY CHANNEL QUARTER QUANTITY_SOLD ------------ ------------ ---------- -------- ------------- Y Box Italy 4 01 21 Y Box Italy 4 02 17 Y Box Italy 4 03 20 . . . Y Box Japan 2 01 35 Y Box Japan 2 02 39 Y Box Japan 2 03 36 Y Box Japan 2 04 46 Y Box Japan 3 01 65 . . . Bounce Italy 2 01 34 Bounce Italy 2 02 43 . . . 9502 rows selected.
  • 39. 45 Pivoting the QUARTER Column in the SH Schema: Example SELECT * FROM (SELECT product, quarter, quantity_sold FROM sales_view) PIVOT (sum(quantity_sold) FOR quarter IN ('01', '02', '03', '04')) ORDER BY product DESC; . . .
  • 40. 47 Unpivoting the QUARTER Column: Conceptual Example 2,000 Q3 Kids Jeans Shorts PRODUCT 3,500 2,000 Q2 1,5002,500 Q4Q1 2,500Q1Kids Jeans 2,000Q2Kids Jeans 3,500Q2Shorts 1,500Q4Kids Jeans Q3 QUARTER 2,000Shorts SUM_OF_QUANTITYPRODUCT
  • 41. 4848 • Univoting the data before 11g requires multiple queries on the table using the UNION ALL operator Unpivoting Before Oracle 11g SELECT * FROM ( SELECT product, '01' AS quarter, Q1_value FROM sales UNION ALL SELECT product, '02' AS quarter, Q2_value FROM sales UNION ALL SELECT product, '03' AS quarter, Q3_value FROM sales UNION ALL SELECT product, '04' AS quarter, Q4_value FROM sales );
  • 42. 49 • An UNPIVOT operation does not reverse a PIVOT operation; instead, it rotates data found in multiple columns of a single row into multiple rows of a single column. • If you are working with pivoted data, UNPIVOT cannot reverse any aggregations that have been made by PIVOT or any other means. Using the UNPIVOT Operator UNPIVOT
  • 43. 50 • The UNPIVOT clause rotates columns from a previously pivoted table or a regular table into rows. You specify: – The measure column or columns to be unpivoted – The name or names for the columns that result from the UNPIVOT operation – The columns that are unpivoted back into values of the column specified in pivot_for_clause • You can use an alias to map the column name to another value. Using the UNPIVOT Clause
  • 44. 51 UNPIVOT Clause Syntax table_reference UNPIVOT [{INCLUDE|EXCLUDE} NULLS] -- specify the measure column(s) to be unpivoted. ( { column | ( column [, column]... ) } unpivot_for_clause unpivot_in_clause ) -- Specify one or more names for the columns that will -- result from the unpivot operation. unpivot_for_clause = FOR { column | ( column [, column]... ) } -- Specify the columns that will be unpivoted into values of -- the column specified in the unpivot_for_clause. unpivot_in_clause = ( { column | ( column [, column]... ) } [ AS { constant | ( constant [, constant]... ) } ] [, { column | ( column [, column]... ) } [ AS { constant | ( constant [, constant]...) } ] ]...)
  • 45. 52 Creating a New Pivot Table: Example . . . CREATE TABLE pivotedtable AS SELECT * FROM (SELECT product, quarter, quantity_sold FROM sales_view) PIVOT (sum(quantity_sold) FOR quarter IN ('01' AS Q1, '02' AS Q2, '03' AS Q3, '04' AS Q4)); SELECT * FROM pivotedtable ORDER BY product DESC;
  • 46. 53 Unpivoting the QUARTER Column in the SH Schema: Example SELECT * FROM pivotedtable UNPIVOT (quantity_sold For Quarter IN (Q1, Q2, Q3, Q4)) ORDER BY product DESC, quarter; . . .
  • 47. 5454 • More information and examples could be found on my Blog: http://www.realdbamagic.com/he/pivot-a-table/ More Examples…
  • 49. 56 • Oracle has enhanced SQL's analytical processing capabilities by introducing a new family of analytic SQL functions. • These analytic functions enable you to calculate and perform: – Rankings and percentiles – Pivoting operations – Moving window calculations – LAG/LEAD analysis – FIRST/LAST analysis – Linear regression statistics Overview of SQL for Analysis and Reporting
  • 50. 5757 • Ability to see one row from another row in the results • Avoid self-join queries • Summary data in detail rows • Slice and dice within the results Why Use Analytic Functions?
  • 51. 58 Using the Analytic Functions Function type Used for Ranking Calculating ranks, percentiles, and n-tiles of the values in a result set Windowing Calculating cumulative and moving aggregates, works with functions such as SUM, AVG, MIN, and so on Reporting Calculating shares such as market share, works with functions such as SUM, AVG, MIN, MAX, COUNT, VARIANCE, STDDEV, RATIO_TO_REPORT, and so on LAG/LEAD Finding a value in a row or a specified number of rows from a current row FIRST/LAST First or last value in an ordered group Linear Regression Calculating linear regression and other statistics
  • 52. 59 • Result set partitions: These are created and available to any aggregate results such as sums and averages. The term “partitions” is unrelated to the table partitions feature. • Window: For each row in a partition, you can define a sliding window of data, which determines the range of rows used to perform the calculations for the current row. • Current row: Each calculation performed with an analytic function is based on a current row within a partition. It serves as the reference point determining the start and end of the window. Concepts Used in Analytic Functions
  • 53. 61 • We can use aggregative functions as analytic functions (i.e. SUM, AVG, MIN, MAX, COUNT etc.) • Each row will get the aggregative value for a given partition without the need for group by clause Reporting Functions
  • 54. 62 • We can have multiple group by on the same row • Getting the raw data along with the aggregated value Reporting Example SELECT last_name, salary, ROUND(AVG(salary) OVER (PARTITION BY department_id),2), COUNT(*) OVER (PARTITION BY manager_id), SUM(salary) OVER (PARTITION BY department_id ORDER BY salary), MAX(salary) OVER () FROM hr.employees;
  • 56. 64 • A ranking function computes the rank of a record compared to other records in the data set based on the values of a set of measures. The types of ranking function are: – RANK and DENSE_RANK functions – PERCENT_RANK function – ROW_NUMBER function – NTILE function – CUME_DIST function Using the Ranking Functions
  • 57. 65 • The RANK function calculates the rank of a value in a group of values, which is useful for top-N and bottom-N reporting. • For example, you can use the RANK function to find the top ten products sold in Boston last year. • When using the RANK function, ascending is the default sort order, which you can change to descending. • Rows with equal values for the ranking criteria receive the same rank. • Oracle Database then adds the number of tied rows to the tied rank to calculate the next rank. Working with the RANK Function RANK ( ) OVER ( [query_partition_clause] order_by_clause )
  • 58. 66 Using the RANK Function: Example SELECT department_id, last_name, salary, RANK() OVER (PARTITION BY department_id ORDER BY salary DESC) "Rank" FROM employees WHERE department_id = 60 ORDER BY department_id, "Rank", salary;
  • 59. 67 • The RANK function can be made to operate within groups—that is, the rank gets reset whenever the group changes. • This is accomplished with the PARTITION BY clause. • The group expressions in the PARTITION BY subclause divide the data set into groups within which RANK operates. • For example, to rank products within each channel by their dollar sales, you could issue a statement similar to the one in the next slide. Per-Group Ranking
  • 60. 68 Per-Group Ranking: Example SELECT channel_desc, calendar_month_desc, TO_CHAR(SUM(amount_sold), '9,999,999,999') SALES$, RANK() OVER (PARTITION BY channel_desc ORDER BY SUM(amount_sold) DESC) AS RANK_BY_CHANNEL FROM sales, products, customers, times, channels WHERE sales.prod_id = products.prod_id AND sales.cust_id = customers.cust_id AND sales.time_id = times.time_id AND sales.channel_Id = channels.channel_id AND times.calendar_month_desc IN ('2000-08', '2000-09', '2000- 10', '2000-11') AND channels.channel_desc IN ('Direct Sales', 'Internet') GROUP BY channel_desc, calendar_month_desc;
  • 61. 69 RANK and DENSE_RANK Functions: Example SELECT department_id, last_name, salary, RANK() OVER (PARTITION BY department_id ORDER BY salary DESC) "Rank", DENSE_RANK() over (partition by department_id ORDER BY salary DESC) "Drank" FROM employees WHERE department_id = 60 ORDER BY department_id, last_name, salary DESC, "Rank" DESC; DENSE_RANK ( ) OVER ([query_partition_clause] order_by_clause)
  • 62. 70 Per-Cube and Rollup Group Ranking SELECT channel_desc, country_iso_code, TO_CHAR(SUM(amount_sold), '9,999,999,999')SALES$, RANK() OVER (PARTITION BY GROUPING_ID(channel_desc, country_iso_code) ORDER BY SUM(amount_sold) DESC) AS RANK_PER_GROUP FROM sales, customers, times, channels, countries WHERE sales.time_id = times.time_id AND sales.cust_id=customers.cust_id AND sales.channel_id = channels.channel_id AND channels.channel_desc IN ('Direct Sales', 'Internet') AND times.calendar_month_desc='2000-09' AND country_iso_code IN ('GB', 'US', 'JP') GROUP BY CUBE(channel_desc, country_iso_code);
  • 63. 71 • Uses rank values in its numerator and returns the percent rank of a value relative to a group of values • PERCENT_RANK of a row is calculated as follows: • The range of values returned by PERCENT_RANK is 0 to 1, inclusive. The first row in any set has a PERCENT_RANK of 0. The return value is NUMBER. Its syntax is: Using the PERCENT_RANK Function (rank of row in its partition - 1) / (number of rows in the partition - 1) PERCENT_RANK () OVER ([query_partition_clause] order_by_clause)
  • 64. 72 Using the PERCENT_RANK Function: Example SELECT department_id, last_name, salary, PERCENT_RANK() OVER (PARTITION BY department_id ORDER BY salary DESC) AS pr FROM hr.employees ORDER BY department_id, pr, salary; . . .
  • 65. 73 • The ROW_NUMBER function calculates a sequential number of a value in a group of values. • When using the ROW_NUMBER function, ascending is the default sort order, which you can change to descending. • Rows with equal values for the ranking criteria receive a different number. Working with the ROW_NUMBER Function ROW_NUMBER ( ) OVER ( [query_partition_clause] order_by_clause )
  • 66. 7474 • ROWNUM is a pseudo column, ROW_NUMBER is an actual function • ROWNUM requires sorting of the entire dataset in order to return ordered list • ROW_NUMBER will only sort the required rows thus giving better performance ROW_NUMBER vs. ROWNUM
  • 67. 7575 • Not really a rank function • Divides an ordered data set into a number of buckets indicated by expr and assigns the appropriate bucket number to each row • The buckets are numbered 1 through expr Working with the NTILE Function NTILE ( expr ) OVER ([query_partition_clause] order_by_clause)
  • 68. 7676 • Different ranking functions may return different results if the data has ties • For example: Summary of Ranking Functions SELECT last_name, salary, ROW_NUMBER() OVER (PARTITION BY department_id ORDER BY salary DESC), RANK() OVER (PARTITION BY department_id ORDER BY salary DESC), DENSE_RANK() OVER (PARTITION BY department_id ORDER BY salary DESC), PERCENT_RANK() OVER (PARTITION BY department_id ORDER BY salary DESC), NTILE(4) OVER (PARTITION BY department_id ORDER BY salary DESC) FROM hr.employees;
  • 70. 78 • LAG provides access to more than one row of a table at the same time without a self-join. • Given a series of rows returned from a query and a position of the cursor, LAG provides access to a row at a given physical offset before that position. • If you do not specify the offset, its default is 1. • If the offset goes beyond the scope of the window, the optional default value is returned. If you do not specify the default, its value is NULL. Using the LAG and LEAD Analytic Functions {LAG | LEAD}(value_expr [, offset ] [, default ]) OVER ([ query_partition_clause ] order_by_clause)
  • 71. 79 Using the LAG and LEAD Analytic Functions: Example SELECT time_id, TO_CHAR(SUM(amount_sold),'9,999,999') AS SALES, TO_CHAR(LAG(SUM(amount_sold),1) OVER (ORDER BY time_id),'9,999,999') AS LAG1, TO_CHAR(LEAD(SUM(amount_sold),1) OVER (ORDER BY time_id),'9,999,999') AS LEAD1 FROM sales WHERE time_id >= TO_DATE('10-OCT-2000') AND time_id <= TO_DATE('14-OCT-2000') GROUP BY time_id;
  • 72. 8080 • For a specified measure, LISTAGG orders data within each group specified in the ORDER BY clause and then concatenates the values of the measure column • Limited to output of 4000 chars Using the LISTAGG Function LISTAGG(measure_expr [, 'delimiter']) WITHIN GROUP (order_by_clause) [OVER query_partition_clause]
  • 73. 8181 Using the LISTAGG Function Example SELECT department_id "Dept", hire_date "Date", last_name "Name", LISTAGG(last_name, ', ') WITHIN GROUP (ORDER BY hire_date, last_name) OVER (PARTITION BY department_id) as "Emp_list" FROM hr.employees WHERE hire_date < '01-SEP-2003' ORDER BY "Dept", "Date", "Name";
  • 74. 8282 • Both are aggregate and analytic functions • Used to retrieve a value from the first or last row of a sorted group, but the needed value is not the sort key • FIRST and LAST functions eliminate the need for self-joins or views and enable better performance Using the FIRST and LAST Functions aggregate_function KEEP (DENSE_RANK FIRST ORDER BY expr [ DESC | ASC ][ NULLS { FIRST | LAST } ] [, expr [ DESC | ASC ] [ NULLS { FIRST | LAST } ] ]... ) [ OVER query_partition_clause ]
  • 75. 8383 FIRST and LAST Aggregate Example SELECT department_id, MIN(salary) KEEP (DENSE_RANK FIRST ORDER BY commission_pct) "Worst", MAX(salary) KEEP (DENSE_RANK LAST ORDER BY commission_pct) "Best" FROM employees GROUP BY department_id ORDER BY department_id;
  • 76. 8484 FIRST and LAST Analytic Example SELECT last_name, department_id, salary, MIN(salary) KEEP (DENSE_RANK FIRST ORDER BY commission_pct) OVER (PARTITION BY department_id) “Worst", MAX(salary) KEEP (DENSE_RANK LAST ORDER BY commission_pct) OVER (PARTITION BY department_id) "Best" FROM employees ORDER BY department_id, salary, last_name;
  • 77. 8585 • Returns the first value in an ordered set of values • If the first value in the set is null, then the function returns NULL unless you specify IGNORE NULLS. This setting is useful for data densification. Using FIRST_VALUE Analytic Function FIRST_VALUE (expr [ IGNORE NULLS ]) OVER (analytic_clause)
  • 78. 8686 Using FIRST_VALUE Analytic Function Example SELECT department_id, last_name, salary, FIRST_VALUE(last_name) OVER (ORDER BY salary ASC ROWS UNBOUNDED PRECEDING) AS lowest_sal FROM (SELECT * FROM employees WHERE department_id = 30 ORDER BY employee_id) ORDER BY department_id, last_name, salary, lowest_sal;
  • 79. 8787 • Returns the last value in an ordered set of values. Using LAST_VALUE Analytic Function LAST_VALUE (expr [ IGNORE NULLS ]) OVER (analytic_clause)
  • 80. 8888 • Returns the N-th values in an ordered set of values • Different default window: RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW Using NTH_VALUE Analytic Function NTH_VALUE (measure_expr, n) [ FROM { FIRST | LAST } ][ { RESPECT | IGNORE } NULLS ] OVER (analytic_clause)
  • 81. 8989 Using NTH_VALUE Analytic Function Example SELECT prod_id, channel_id, MIN(amount_sold), NTH_VALUE ( MIN(amount_sold), 2) OVER (PARTITION BY prod_id ORDER BY channel_id ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) nv FROM sh.sales WHERE prod_id BETWEEN 13 and 16 GROUP BY prod_id, channel_id;
  • 83. 9191 • The windowing_clause gives some analytic functions a further degree of control over this window within the current partition • The windowing_clause can only be used if an order_by_clause is present Window Functions
  • 84. 9292 Windows can be by RANGE or ROWS Possible values for start_point and end_point UNBOUNDED PRECEDING The window starts at the first row of the partition. Only available for start points. UNBOUNDED FOLLOWING The window ends at the last row of the partition. Only available for end points. CURRENT ROW The window starts or ends at the current row value_expr PRECEDING A physical or logical offset before the current row. When used with RANGE, can also be an interval literal value_expr FOLLOWING As above, but an offset after the current row RANGE BETWEEN start_point AND end_point ROWS BETWEEN start_point AND end_point
  • 85. 9393 • The windows are limited to the current partition • Generally, the default window is the entire work set unless said otherwise Window Limitations
  • 86. 9494 Shortcuts • Useful shortcuts for the windowing clause: ROWS UNBOUNDED PRECEDING ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ROWS 10 PRECEDING ROWS BETWEEN 10 PRECEDING AND CURRENT ROW ROWS CURRENT ROW ROWS BETWEEN CURRENT ROW AND CURRENT ROW
  • 87. 9595 • Cumulative aggregation • Sliding average over proceeding and/or following rows • Using the RANGE parameter to filter aggregation records Windowing Clause Useful Usages
  • 88. Top-N and Paging Queries In Oracle 12c 96
  • 89. 97 Top-N Queries • A Top-N query is used to retrieve the top or bottom N rows from an ordered set • Combining two Top-N queries gives you the ability to page through an ordered set • Oracle 12c has introduced the row limiting clause to simplify Top-N queries
  • 90. 9898 • This is ANSI syntax • The default offset is 0 • Null values in offset, rowcount or percent will return no rows Top-N in 12c [ OFFSET offset { ROW | ROWS } ] [ FETCH { FIRST | NEXT } [ { rowcount | percent PERCENT } ] { ROW | ROWS } { ONLY | WITH TIES } ]
  • 91. 9999 Top-N Examples SELECT last_name, salary FROM hr.employees ORDER BY salary FETCH FIRST 4 ROWS ONLY; SELECT last_name, salary FROM hr.employees ORDER BY salary FETCH FIRST 4 ROWS WITH TIES; SELECT last_name, salary FROM hr.employees ORDER BY salary DESC FETCH FIRST 10 PERCENT ROWS ONLY;
  • 92. 100100 • Before 12c we had to use the rownum pseudo column to filter out rows • That will require sorting the entire rowset Paging Before 12c SELECT val FROM (SELECT val, rownum AS rnum FROM (SELECT val FROM rownum_order_test ORDER BY val) WHERE rownum <= 10) WHERE rnum >= 5;
  • 93. 101101 • After 12c we have a syntax improvement for paging using the Top-N queries • This will use ROW_NUMBER and RANK in the background – there is no real optimization improvements Paging in Oracle 12c SELECT val FROM rownum_order_test ORDER BY val OFFSET 4 ROWS FETCH NEXT 5 ROWS ONLY;
  • 94. 102102 • More information and examples could be found on my blog: http://www.realdbamagic.com/he/12c-top-n-query/ More Examples
  • 95. 103103 • Analytic functions has positive impact on performance for the most part • Using analytic functions can reduce the number of table scans and reduce IO consumption • The query might use more CPU and/or memory but it will usually run faster than the same result without analytic functions • Top-N queries might struggle with cardinality evaluation when using the “With Ties” option Analytic Functions and Performance
  • 97. 105 • You can use hierarchical queries to retrieve data based on a natural hierarchical relationship between rows in a table. • A relational database does not store records in a hierarchical way; therefore, a hierarchical query is possible only when a relationship exists between rows in a table. • However, where a hierarchical relationship exists between the rows of a single table, a process called “tree walking” enables the hierarchy to be constructed. • A hierarchical query is a method of reporting, with the branches of a tree in a specific order. Using Hierarchical Queries
  • 98. 106106 • Getting all employees that report directly or indirectly to a manager • Managing documents and folders • Managing privileges • Aggregating levels on the same row Business Challenges
  • 99. Using Hierarchical Queries: Example Sample Data from the EMPLOYEES Table • In the EMPLOYEES table in the HR schema, Kochhar, De Haan, and Hartstein report to the MANAGER_ID 100, which is King’s EMPLOYEE_ID. …
  • 100. 108 Natural Tree Structure De Haan HunoldWhalen Kochhar Higgins Mourgos Zlotkey Rajs Davies Matos Gietz Ernst Lorentz Hartstein Fay Abel Taylor Grant Vargas MANAGER_ID = 100 (Child) EMPLOYEE_ID = 100 (Parent) . . . . . . . . . . . . . . . King
  • 101. 109 condition: Hierarchical Queries: Syntax expr comparison_operator expr SELECT [LEVEL], column, expr... FROM table [WHERE condition(s)] [START WITH condition(s)] [CONNECT BY PRIOR condition(s)] ;
  • 102. 110 – Use the START WITH clause to specify the starting point, that is, the row or rows to be used as the root of the tree: • Specifies the condition that must be met • Accepts any condition that is valid in a WHERE clause – For example, using the HR.EMPLOYEES table, start with the employee whose last name is Kochhar. Walking the Tree: Specifying the Starting Point . . . START WITH last_name = 'Kochhar' START WITH column1 = value
  • 103. 111 • The direction of the query is determined by the CONNECT BY PRIOR column placement. • The PRIOR operator refers to the parent row. • For example, you can walk the tree from top down using the EMPLOYEES table as follows: Walking the Tree: Specifying the Direction of the Query CONNECT BY PRIOR column1 = column2 . . . CONNECT BY PRIOR employee_id = manager_id . . . Parent key Child key
  • 104. 112 Hierarchical Query Example: Using the CONNECT BY Clause SELECT employee_id, last_name, manager_id FROM hr.employees CONNECT BY PRIOR employee_id = manager_id; . . .
  • 105. 113 Specifying the Direction of the Query: From the Top Down SELECT last_name||' reports to '|| PRIOR last_name "Walk Top Down" FROM hr.employees START WITH last_name = 'King' CONNECT BY PRIOR employee_id = manager_id ; . . .
  • 106. 114 Specifying the Direction of the Query: From the Bottom Up SELECT employee_id, last_name, job_id, manager_id FROM hr.employees START WITH employee_id = 101 CONNECT BY PRIOR manager_id = employee_id ;
  • 107. 115 Using the LEVEL Pseudocolumn Level 1 root/ parent Level 3 parent/ child/leaf Level 4 leaf De Haan King HunoldWhalen Kochhar Higgins Mourgos Zlotkey Rajs Davies Matos Gietz Ernst Lorentz Hartstein Fay Abel Taylor Grant Vargas Level 2 parent/ child
  • 108. 116 Using the LEVEL Pseudocolumn: Example SELECT employee_id, last_name, manager_id, LEVEL FROM hr.employees START WITH employee_id = 100 CONNECT BY PRIOR employee_id = manager_id ORDER siblings BY last_name; . . .
  • 109. 117 • Create a report displaying company management levels beginning with the highest level and indenting each of the following levels. Formatting Hierarchical Reports Using LEVEL and LPAD SELECT LPAD(last_name, LENGTH(last_name)+(LEVEL*2)- 2,'_') AS org_chart FROM hr.employees START WITH first_name = 'Steven' AND last_name = 'King' CONNECT BY PRIOR employee_id = manager_id ORDER SIBLINGS BY last_name;
  • 110. 118 – Use the WHERE clause to eliminate a node. – Use the CONNECT BY clause to eliminate a branch. Pruning Nodes and Branches Kochhar Higgins Gietz Whalen Kochhar HigginsWhalen Gietz . . . WHERE last_name != 'Higgins' . . . CONNECT BY PRIOR employee_id = manager_id AND last_name != 'Higgins' 1 2
  • 111. 119 Pruning Branches Example 1: Eliminating a Node SELECT department_id, employee_id,last_name, job_id, salary FROM hr.employees WHERE last_name != 'Higgins' START WITH manager_id IS NULL CONNECT BY PRIOR employee_id = manager_id; . . . . . . . . .
  • 112. 120 Pruning Branches Example 2: Eliminating a Branch SELECT department_id, employee_id,last_name, job_id, salary FROM hr.employees START WITH manager_id IS NULL CONNECT BY PRIOR employee_id = manager_id AND last_name != 'Higgins'; . . .
  • 113. 121121 • Join happens before connect by • Where is happening after connect by • Regular order by will rearrange the returning rows • Sibling order by will rearrange the returning rows for each level Order of Precedence
  • 114. 122122 Other Connect By Functions • CONNECT_BY_ISCYCLE • CONNECT_BY_ISLEAF • CONNECT_BY_ROOT • SYS_CONNECT_BY_PATH
  • 115. 123123 • ANSI SQL:2008 (Oracle 11g) introduced a new way to run hierarchical queries: Recursive Subquery Factoring (RSF) • Using the with clause, making queries easier to write New Syntax: Recursive Subquery Factoring
  • 116. 124124 Recursive Subquery Factoring Example with mytree(id, parent_id, "level") as ( select id, parent_id, 1 as "level" from temp_v where id = 1 union all select temp_v.id, temp_v.parent_id, mytree."level" + 1 from temp_v, mytree where temp_v.parent_id = mytree.id ) Select * from mytree; Stop Condition Actual Recursion
  • 117. 125125 • Recursion and Hierarchies might have bad impact on performance • Watch out for mega-trees – it has CPU and memory impact • Using recursion might lead for multiple IO reads of the same blocks Warning: Recursion might be Bad for Performance
  • 119. 127127 • Identify and group rows with consecutive values • Consecutive in this regards – row after row • Uses regular expression like syntax to find patterns What is Pattern Matching
  • 120. 128128 • Finding sequences of events in security applications • Locating dropped calls in a CDR listing • Financial price behaviors (V-shape, W-shape U-shape, etc.) • Fraud detection and sensor data analysis Common Business Challenges
  • 121. 129129 MATCH_RECOGNIZE Syntax SELECT FROM [row pattern input table] MATCH_RECOGNIZE ( [ PARTITION BY <cols> ] [ ORDER BY <cols> ] [ MEASURES <cols> ] [ ONE ROW PER MATCH | ALL ROWS PER MATCH ] [ SKIP_TO_option] PATTERN ( <row pattern> ) DEFINE <definition list> )
  • 122. 130130 • PARTITION BY divides the data in to logical groups • ORDER BY orders the data in each logical group • MEASURES define the data measures of the pattern • ONE/ALL ROW PER MATCH defines what to do with the pattern – return one row or all rows • PATTERN says what the pattern actually is • DEFINE gives us the condition that must be met for a row to map to the pattern variables Basix Syntax Legend
  • 123. 131131 • Find Simple V-Shape with 1 row output per match MATCH_RECOGNIZE Example SELECT * FROM Ticker MATCH_RECOGNIZE ( PARTITION BY symbol ORDER BY tstamp MEASURES STRT.tstamp AS start_tstamp, LAST(DOWN.tstamp) AS bottom_tstamp, LAST(UP.tstamp) AS end_tstamp ONE ROW PER MATCH AFTER MATCH SKIP TO LAST UP PATTERN (STRT DOWN+ UP+) DEFINE DOWN AS DOWN.price < PREV(DOWN.price), UP AS UP.price > PREV(UP.price) ) MR ORDER BY MR.symbol, MR.start_tstamp;
  • 124. 132132 What Will Be Matched?
  • 125. 133133 • Our goal: find uninterrupted sequences in a book • This can be useful for detecting missing records or sequential behavior Pages in a Book Example
  • 126. 134 Building Our Query 1. Define input 2. Pattern Matching 3. Order input 4. Process pattern 5. using defined conditions 6. Output: rows per match 7. Output: columns per row 8. Where to go after match? SELECT * FROM book_pages MATCH_RECOGNIZE ( ORDER BY page PATTERN (A B*) DEFINE B AS page = PREV(page)+1 ONE ROW PER MATCH MEASURES A.page firstpage, LAST(page) lastpage, COUNT(*) cnt AFTER MATCH SKIP PAST LAST ROW ); SELECT * FROM book_pages MATCH_RECOGNIZE ( ORDER BY page MEASURES A.page firstpage, LAST(page) lastpage, COUNT(*) cnt ONE ROW PER MATCH AFTER MATCH SKIP PAST LAST ROW PATTERN (A B*) DEFINE B AS page = PREV(page)+1 );
  • 127. 135135135135 And The Output… FIRSTPAGE LASTPAGE CNT ---------- ---------- ---------- 1 3 3 5 7 3 10 15 6 42 42 1
  • 128. 136136136136 • Concatenation: No operator between elements. • Quantifiers: – * 0 or more matches. – + 1 or more matches – ? 0 or 1 match. – {n} Exactly n matches. – {n,} n or more matches. – {n, m} Between n and m (inclusive) matches. – {, m} Between 0 an m (inclusive) matches. • Alternation: | • Grouping: () Supported Regular Expression Patterns
  • 129. 137137 • CLASSIFIER(): Which pattern variable applies to which row • MATCH_NUMBER(): Which rows are members of which match • PREV(): Access to a column/expression in a previous row • NEXT(): Access to a column/expression in the next row • LAST(): Last value within the pattern match • FIRST(): First value within the pattern match • COUNT(), AVG(), MAX(), MIN(), SUM() Functions
  • 130. 138138 • Find suspicious transfers – a large transfer after 3 small ones Example: All Rows Per Match SELECT userid, match_id, pattern_variable, time, amount FROM (SELECT * FROM event_log WHERE event = 'transfer') MATCH_RECOGNIZE ( PARTITION BY userid ORDER BY time MEASURES MATCH_NUMBER() match_id, CLASSIFIER() pattern_variable ALL ROWS PER MATCH PATTERN ( x{3,} y) DEFINE x AS (amount < 2000 AND LAST(x.time) -FIRST(x.time) < 30), y AS (amount >= 1000000 AND y.time-LAST(x.time) < 10) );
  • 131. 139139 • MATCH_ID shows current match sequence • PATTERN_VARIABLE show which variable was applied • USERID is the partition key The Output USERID MATCH_ID PATTERN_VA TIME AMOUNT -------- ---------- ---------- --------- ---------- john 1 X 06-JAN-12 1000 john 1 X 15-JAN-12 1500 john 1 X 20-JAN-12 1500 john 1 X 23-JAN-12 1000 john 1 Y 26-JAN-12 1000000
  • 132. 140140 • Same as before – show one row per match Example: One Row Per Match SELECT userid, first_trx, last_trx, amount FROM (SELECT * FROM event_log WHERE event = 'transfer') MATCH_RECOGNIZE ( PARTITION BY userid ORDER BY time MEASURES FIRST(x.time) first_trx, y.time last_trx, y.amount amount ONE ROW PER MATCH PATTERN ( x{3,} y ) DEFINE x AS (amount < 2000 AND LAST(x.time) -FIRST(x.time) < 30), y AS (amount >= 1000000 AND y.time-LAST(x.time) < 10) );
  • 133. 141141 • USERID is the partition key • FIRST_TRX is a calculated measure • AMOUNT and LAST_TRX are measures The Output USERID FIRST_TRX LAST_TRX AMOUNT -------- --------- --------- ---------- john 06-JAN-12 26-JAN-12 1000000
  • 134. 142142 • Test all cases: pattern matching can be very tricky • Don’t forget to test your data with no matches • There is no LISTAGG and no DISTINCT when using match recognition • Pattern variables cannot be used as bind variables Few Last Tips
  • 135. Using XML with SQL 143
  • 136. 144144 • XML stand for Extensible Markup Language • Defines a set of rules for encoding documents in a format which is both human-readable and machine-readable • Data is unstructured and can be transferred easily to other system What is XML
  • 137. 145145 • Root • Element • Attribute • Forest • XML Fragment • XML Document XML Terminology
  • 138. 146146 What Does XML Look Like? <?xml version="1.0"?> <ROWSET> <ROW> <USERNAME>SYS</USERNAME> <USER_ID>0</USER_ID> <CREATED>28-JAN-08</CREATED> </ROW> <ROW> <USERNAME>SYSTEM</USERNAME> <USER_ID>5</USER_ID> <CREATED>28-JAN-08</CREATED> </ROW> </ROWSET>
  • 139. 147147 • Concatenating strings – building the XML manually. This is highly not recommended • Using DBMS_XMLGEN • Using ANSI SQL:2003 XML functions Generating XML From Oracle
  • 140. 148148 • The DBMS_XMLGEN package converts the results of a SQL query to a canonical XML format • The package takes an arbitrary SQL query as input, converts it to XML format, and returns the result as a CLOB • Using the DBMS_XMLGEN we can create contexts and use it to build XML documents • Old package – exists since Oracle 9i Using DBMS_XMLGEN
  • 141. 149149 Example of Using DBMS_XMLGEN select dbms_xmlgen.getxml(q'{ select column_name, data_type from all_tab_columns where table_name = 'EMPLOYEES' and owner = 'HR'}') from dual / <?xml version="1.0"?> <ROWSET> <ROW> <COLUMN_NAME>EMPLOYEE_ID</COLUMN_NAME> <DATA_TYPE>NUMBER</DATA_TYPE> </ROW> <ROW> <COLUMN_NAME>FIRST_NAME</COLUMN_NAME> <DATA_TYPE>VARCHAR2</DATA_TYPE> </ROW> [...] </ROWSET>
  • 142. 150150 • DBMS_XMLGEN is an old package (9.0 and 9i) • Any context change requires complex PL/SQL • There are improved ways to use XML in queries • Use DBMS_XMLGEN for the “quick and dirty” solution only Why Not Use DBMS_XMLGEN
  • 143. 151151 • Introduced in ANSI SQL:2003 – Oracle 9iR2 and 10gR2 • Standard functions that can be integrated into queries • Removes the need for PL/SQL code to create XML documents Standard XML Functions
  • 144. 152152 XMLELEMENT The basic unit for turning column data into XML fragments XMLATTRIBUTES Converts column data into attributes of the parent element XMLFOREST Allows us to process multiple columns at once XMLAGG Aggregate separate Fragments into a single fragment XMLROOT Allows us to place an XML tag at the start of our XML document XML Functions
  • 145. 153153 XMLELEMENT SELECT XMLELEMENT("name", e.last_name) AS employee FROM employees e WHERE e.employee_id = 202; EMPLOYEE ------------------------------ <name>Fay</name>
  • 146. 154154 XMLELEMENT (2) SELECT XMLELEMENT("employee", XMLELEMENT("works_number", e.employee_id), XMLELEMENT("name", e.last_name) ) AS employee FROM employees e WHERE e.employee_id = 202; EMPLOYEE ---------------------------------------------------------- <employee><works_number>202</works_number><name>Fay</name> </employee>
  • 147. 155155 XMLATTRIBUTES SELECT XMLELEMENT("employee", XMLATTRIBUTES( e.employee_id AS "works_number", e.last_name AS "name") ) AS employee FROM employees e WHERE e.employee_id = 202; EMPLOYEE ---------------------------------------------------------- <employee works_number="202" name="Fay"></employee>
  • 148. 156156 XMLFOREST SELECT XMLELEMENT("employee", XMLFOREST( e.employee_id AS "works_number", e.last_name AS "name", e.phone_number AS "phone_number") ) AS employee FROM employees e WHERE e.employee_id = 202; EMPLOYEE ---------------------------------------------------------- <employee><works_number>202</works_number><name>Fay</name> <phone_number>603.123.6666</phone_number></employee>
  • 149. 157157 XMLFOREST Problem SELECT XMLELEMENT("employee", XMLFOREST( e.employee_id AS "works_number", e.last_name AS "name", e.phone_number AS "phone_number") ) AS employee FROM employees e WHERE e.employee_id in (202, 203); EMPLOYEE ---------------------------------------------------------- <employee><works_number>202</works_number><name>Fay</name> <phone_number>603.123.6666</phone_number></employee> <employee><works_number>203</works_number><name>Mavris</name> <phone_number>515.123.7777</phone_number></employee> 2 row selected.
  • 150. 158158 XMLAGG SELECT XMLAGG( XMLELEMENT("employee", XMLFOREST( e.employee_id AS "works_number", e.last_name AS "name", e.phone_number AS "phone_number") )) AS employee FROM employees e WHERE e.employee_id in (202, 203); EMPLOYEE ---------------------------------------------------------- <employee><works_number>202</works_number><name>Fay</name> <phone_number>603.123.6666</phone_number></employee><employee> <works_number>203</works_number><name>Mavris</name> <phone_number>515.123.7777</phone_number></employee> 1 row selected.
  • 151. 159159 • Creating a well formed XML document XMLROOT SELECT XMLROOT ( XMLELEMENT("employees", XMLAGG( XMLELEMENT("employee", XMLFOREST( e.employee_id AS "works_number", e.last_name AS "name", e.phone_number AS "phone_number") ))), VERSION '1.0') AS employee FROM employees e WHERE e.employee_id in (202, 203);
  • 152. 160160 • Well formed, version bound, beatified XML: XMLROOT EMPLOYEE ------------------------------------------ <?xml version="1.0"?> <employees> <employee> <works_number>202</works_number> <name>Fay</name> <phone_number>603.123.6666</phone_number> </employee> <employee> <works_number>203</works_number> <name>Mavris</name> <phone_number>515.123.7777</phone_number> </employee> </employees>
  • 153. 161161 • Using the XQuery language we can create, read and manipulate XML documents • Two main functions: XMLQuery and XMLTable • XQuery is about sequences - XQuery is a general sequence-manipulation language • Each sequence can contain numbers, strings, Booleans, dates, or other XML fragments Using XQuery
  • 154. 162 Creating XML Document using XQuery SELECT warehouse_name, EXTRACTVALUE(warehouse_spec, '/Warehouse/Area'), XMLQuery( 'for $i in /Warehouse where $i/Area > 50000 return <Details> <Docks num="{$i/Docks}"/> <Rail> { if ($i/RailAccess = "Y") then "true" else "false" } </Rail> </Details>' PASSING warehouse_spec RETURNING CONTENT) "Big_warehouses" FROM warehouses;
  • 155. 163 Creating XML Document using XQuery WAREHOUSE_ID Area Big_warehouses ------------ --------- -------------------------------------------------------- 1 25000 2 50000 3 85700 <Details><Docks></Docks><Rail>false</Rail></Details> 4 103000 <Details><Docks num="3"></Docks><Rail>true</Rail></Details> . . .
  • 156. 164164 Example: Using XMLTable to Read XML SELECT lines.lineitem, lines.description, lines.partid, lines.unitprice, lines.quantity FROM purchaseorder, XMLTable('for $i in /PurchaseOrder/LineItems/LineItem where $i/@ItemNumber >= 8 and $i/Part/@UnitPrice > 50 and $i/Part/@Quantity > 2 return $i' PASSING OBJECT_VALUE COLUMNS lineitem NUMBER PATH '@ItemNumber', description VARCHAR2(30) PATH 'Description', partid NUMBER PATH 'Part/@Id', unitprice NUMBER PATH 'Part/@UnitPrice', quantity NUMBER PATH 'Part/@Quantity') lines;
  • 157. Oracle 12c JSON Support 165
  • 158. 166166 • Javascript Object Notation • Converts database tables to a readable document – just like XML but simplier • Very common in NoSQL and Big Data solutions What is JSON {"FirstName" : "Zohar", "LastName" : "Elkayam", "Age" : 36, "Connection" : [ {"Type" : “Email", "Value" : "[email protected]"}, {"Type" : “Twitter", "Value" : “@realmgic"}, {"Type" : "Site", "Value" : "www.realdbamagic.com"}, ]}
  • 159. 167167 • Ability to store data without requiring a Schema – Store semi-structured data in its native (aggregated) form • Ability to query data without knowledge of Schema • Ability to index data with knowledge of Schema JSON Benefits
  • 160. 168168 • Oracle supports JSON since version 12.1.0.2 • JSON documents stored in the database using existing data types: VARCHAR2, CLOB or BLOB • External JSON data sources accessible through external tables including HDFS • Data accessible via REST API Oracle JSON Support
  • 161. 169169 • Simple well understood model • CRUD operations are mapped to HTTP Verbs – Create / Update : PUT / POST – Retrieve : GET – Delete : DELETE – QBE, Bulk Update, Utilitiy functions : POST • Stateless REST based API for JSON documents
  • 162. 170170 • Similar role to XPATH in XML • Syntactically similar to Java Script (. and [ ]) • Compatible with Java Script JSON Path Expression
  • 163. 171171 • There are few common JSON Operators: Common JSON SQL Functions JSON_EXISTS Checks if a value exists in the JSON JSON_VALUE Retrieve a scalar value from JSON JSON_QUERY Query a string from JSON Document JSON_TABLE Query data from JSON Document (like XMLTable)
  • 164. 172172 • Extract JSON fragment from JSON document JSON_QUERY select count(*) from J_PURCHASEORDER where JSON_EXISTS( PO_DOCUMENT, '$.ShippingInstructions.Address.state‘) /
  • 165. 173173 • Generate rows from a JSON Array • Pivot properties / key values into columns • Use Nested Path clause to process multi-level collections with a single JSON_TABLE operator. Using JSON_TABLE
  • 166. 174174 • 1 Row of output for each row in table Example: JSON_TABLE select M.* from J_PURCHASEORDER p, JSON_TABLE( p.PO_DOCUMENT, '$' columns PO_NUMBER NUMBER(10) path '$.PONumber', REFERENCE VARCHAR2(30 CHAR) path '$.Reference', REQUESTOR VARCHAR2(32 CHAR) path '$.Requestor', USERID VARCHAR2(10 CHAR) path '$.User', COSTCENTER VARCHAR2(16) path '$.CostCenter' ) M where PO_NUMBER > 1600 and PO_Number < 1605 /
  • 167. 175175 • 1 row output for each member of LineItems array `` Example: JSON_TABLE (2) select D.* from J_PURCHASEORDER p, JSON_TABLE( p.PO_DOCUMENT, '$' columns( PO_NUMBER NUMBER(10) path '$.PONumber', NESTED PATH '$.LineItems[*]' columns( ITEMNO NUMBER(16) path '$.ItemNumber', UPCCODE VARCHAR2(14 CHAR) path '$.Part.UPCCode‘ )) ) D where PO_NUMBER = 1600 or PO_NUMBER = 1601 /
  • 168. 176176 • Known Query Patterns : JSON Path expression – Functional indexes using JSON_VALUE and, JSON_EXISTS – Materialized View using JSON_TABLE() • Ad-hoc Query Strategy – Based on Oracle’s full text index (Oracle Text) – Support ad-hoc path, value and keyword query search using JSON Path expressions JSON Indexing
  • 170. 178178 • Regular expression (regexp) is a sequence of characters that define a search pattern • Commonly used for smart “Search and Replace” of patterns and for input validations of text • Widely introduced in Oracle 10g (and it even existed even before that) Regular Expression
  • 171. 179179 Common REGEXP Functions and Operators REGEXP_LIKE Perform regular expression matching REGEXP_REPLACE Extends the functionality of the REPLACE function by using patterns REGEXP_SUBSTR Extends the functionality of the SUBSTR function by using patterns REGEXP_COUNT Count the number of matches of the pattern in a given string REGEXP_INSTR Extends the functionality of the INSTR function by using patterns
  • 172. 180180180180 • Concatenation: No operator between elements. • Quantifiers: – . Matches any character in the database character set – * 0 or more matches – + 1 or more matches – ? 0 or 1 match – {n} Exactly n matches – {n,} n or more matches – {n, m} Between n and m (inclusive) matches – {, m} Between 0 an m (inclusive) matches • Alternation: [|] • Grouping: () Supported Regular Expression Patterns
  • 173. 181181 Supported Regular Expression Patterns Value Description ^ Matches the beginning of a string. If used with a match_parameter of 'm', it matches the start of a line anywhere within expression. $ Matches the end of a string. If used with a match_parameter of 'm', it matches the end of a line anywhere withinexpression. W Matches a nonword character. s Matches a whitespace character. S matches a non-whitespace character. A Matches the beginning of a string or matches at the end of a string before a newline character. Z Matches at the end of a string.
  • 174. 182182 Character Class Description [:alnum:] Alphanumeric characters [:alpha:] Alphabetic characters [:blank:] Blank Space Characters [:cntrl:] Control characters (nonprinting) [:digit:] Numeric digits [:graph:] Any [:punct:], [:upper:], [:lower:], and [:digit:] chars [:lower:] Lowercase alphabetic characters [:print:] Printable characters [:punct:] Punctuation characters [:space:] Space characters (nonprinting), such as carriage return, newline, vertical tab, and form feed [:upper:] Uppercase alphabetic characters [:xdigit:] Hexidecimal characters Character Classes
  • 176. 184184 • Regular expressions might be slow when used on large amount of data • Writing regular expression can be very tricky – make sure your pattern is correct • Oracle REGEXP syntax is not standard, regular expression might not work or partially work causing wrong results • There can only be up to 9 placeholders in a given quantifier Pitfalls
  • 177. SQLcl Introduction The Next Generation of SQL*Plus? 185
  • 178. 186186 • Introduced in Oracle 5 (1985) • Looks very simple but has tight integration with other Oracle infrastructure and tools • Very good for reporting, scripting, and automation • Replaced old CLI tool called … UFI (“User Friendly Interface”) SQL*Plus
  • 179. 187187 • Nothing really wrong with SQL*Plus – it is being updated constantly but it is missing a lot of functionality • SQL*Plus forces us to use GUI tools to complete some basic tasks • Easy to understand, a bit hard to use • Not easy for new users or developers What’s Wrong With SQL*Plus?
  • 180. 188188 • SQLcl is a new command line interface (CLI) for SQL users and DBAs • It is part of the SQL Developer suite – developed by the same team: Oracle Database Development Tools Team • Can do most of what SQL*Plus does and much more • Minimal installation, minimal requirements Introducing SQLcl
  • 181. 189189 • It’s still in the early adopter version (current version: 4.2.0.15.295.1605 RC, October 23, 2015) • Uses Java, one version for Windows, Linux and OS X • Planned to be shipped out with Oracle Database 12cR2 (“within the next 12 month”) Introducing SQLcl (cont.)
  • 182. 190190 • Early Adopter version/RC • QA still logging bugs from SQL*Plus regression tests • Adding support for existing SQL*Plus commands and syntax • Adding new commands • But can it do...? – Yes – Not yet – No Current Status
  • 183. 191191 • Download from: SQL Developer Download page • Unzip the file • Run it Installing
  • 184. What Can It Do? 192
  • 185. 193193 • Use the tab key to complete commands • Can be used to list tables, views or other queriable objects • Can be used to replace the * with actual column names • Use the arrow keys to move around the command • Use CTRL+W and CTRL+S to jump to the beginning/end of commands Object Completion and Easy Edit
  • 186. 194194 • 100 command history buffer • Commands are persistent between sessions (watch out for security!) • Use UP and DOWN arrow keys to access old commands • Usage: history history usage History script history full History clear [session?] • Load from history into command buffer: history <number> Command History
  • 187. 195195 • Describe lists the column of the tables just like SQL*Plus • Information shows column names, default values, indexes and constraints. • In 12c database information shows table statistics and In memory status • Works for table, views, sequences, and code objects • Info+ shows additional information regarding column statistics and column histograms Describe, Information and info+
  • 188. 196196 • Outputting query results becomes easier with the “set sqlformat” command (also available in SQL Developer) • We can create a query in the “regular” way and then switch between the different output styles: – ANSIConsole – Fixed column size output – XML or JSON output – HTML output generates a built in search field and a responsive html output for the result only Generating Pretty Output
  • 189. 197197 • We can generate loader ready output (with “|” as a delimiter) • We can generate insert commands • We can easily generate CSV output • Usage: set sqlformat { csv,html,xml,json,ansiconsole,insert, loader,fixed,default} Generating Other Useful Outputs
  • 190. 198198 • Loads a comma separated value (csv) file into a table • The first row of the file must be a header row and the file must be encoded UTF8 • The load is processed with 50 rows per batch • Usage: LOAD [schema.]table_name[@db_link] file_name Load Data From CSV File
  • 191. 199199 • There is a lot in SQL than meets the eye • Wise use of analytic queries can be good for readability and performance • Recursive queries are good replacement for the old connect by prior but a little dangerous • Oracle 12c features are really cool! • Look out for SQLcl: it’s cool and it’s going places! Summary
  • 192. 200200 • The Model clause • Using the WITH clause • Adding PL/SQL to our SQL (Oracle 12c) • Hints and other tuning considerations • The SQL reference book is 1906 pages long. We didn’t talk about most of it… What Did We Not Talk About?
  • 193. Q&A Any Questions? Now will be the time! 201