Top Banner
® Recursive Queries After completing this module, you will be able to: Identify the need for recursive derived table vs. (non-recursive) derived table. Discern the different parts of the recursive query structure. Prevent forms of continual looping through a hierarchy. Interpret the two-column result set derived by the recursive query. “Flatten” the vertical (two-column) result into a horizontal structure. Teradata Corporation Copyright ©2007–2014. All Rights Reserved.
25

After completing this module, you will be able to ...dbmanagement.info/Books/MIX/Module03-Recursive_TeraData.pdf · ®Building Tables for Recursive Processing Suppose we want to find

Mar 27, 2018

Download

Documents

lythuan
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: After completing this module, you will be able to ...dbmanagement.info/Books/MIX/Module03-Recursive_TeraData.pdf · ®Building Tables for Recursive Processing Suppose we want to find

® Recursive Queries

After completing this module, you will be able to:

• Identify the need for recursive derived table vs. (non-recursive) derived table.

• Discern the different parts of the recursive query structure.

• Prevent forms of continual looping through a hierarchy.

• Interpret the two-column result set derived by the recursive query.

• “Flatten” the vertical (two-column) result into a horizontal structure.

Teradata Corporation Copyright ©2007–2014. All Rights Reserved.

Page 2: After completing this module, you will be able to ...dbmanagement.info/Books/MIX/Module03-Recursive_TeraData.pdf · ®Building Tables for Recursive Processing Suppose we want to find

® Recursive Query Description

Recursive queries are queries that process the same data more than once.

These queries are useful for processing data that is hierarchical in nature, i.e.,

• Bill of materials• Corporate org charts• Airline flight plans

Each pass over the data can add new rows to the recursive table.

To process those new rows, another pass over the data is made.

Assume a table has all direct airline flights to Los Angeles for a particular airline:

You can see all direct flights from New York by reading through the table once.You can see all one-stopover flights from NY by reading through the table twice.You can see all two-stopover flights from NY by reading through the table three times.

Each iteration may require a temporary table to be built and a new query to be run.

Page 3: After completing this module, you will be able to ...dbmanagement.info/Books/MIX/Module03-Recursive_TeraData.pdf · ®Building Tables for Recursive Processing Suppose we want to find

® Building Tables for Recursive Processing

Suppose we want to find all routes originating from LAX having at most 3 stopovers.First, we begin with a Flights table that contains direct flights only and no stopovers.

CREATE TABLE Flights( Origin CHAR(3) NOT NULL,Destination CHAR(3) NOT NULL,Cost INT );

SELECT * FROM Flights ORDER BY 1;

Origin Destination CostOrigin Destination CostOrigin Destination CostOrigin Destination Cost------------------------------------ ---------------------------------------------------- ------------------------ATL BOS 140ATL BOS 140ATL BOS 140ATL BOS 140LAX BOS 300LAX BOS 300LAX BOS 300LAX BOS 300LAX ATL 250LAX ATL 250LAX ATL 250LAX ATL 250LAX SFO 90LAX SFO 90LAX SFO 90LAX SFO 90ORD BOS 180ORD BOS 180ORD BOS 180ORD BOS 180SFO ORD 275SFO ORD 275SFO ORD 275SFO ORD 275

Show all direct flights.

SELECT * FROM Flights WHERE Origin = 'LAX' ;

Show all direct flights originating from Los Angeles

Origin Destination CostOrigin Destination CostOrigin Destination CostOrigin Destination Cost------------------------------------ ---------------------------------------------------- ------------------------LAX BOS 300LAX BOS 300LAX BOS 300LAX BOS 300LAX ATL 250LAX ATL 250LAX ATL 250LAX ATL 250LAX SFO 90LAX SFO 90LAX SFO 90LAX SFO 90

Page 4: After completing this module, you will be able to ...dbmanagement.info/Books/MIX/Module03-Recursive_TeraData.pdf · ®Building Tables for Recursive Processing Suppose we want to find

® Creating a “One Stopover” Table

Assume that we don't have the recursive feature available, but we wish to find all LAX-based flights with one stopover.

Create a new table containing all flights originating at LAX with one stopover

CREATE TABLE Flights_1Stop(Origin, Destination, Cost) AS (SELECT Flight1.Origin,

Flight2.Destination, Flight1.Cost+Flight2.Cost AS Price

FROM Flights Flight1 JOIN Flights Flight2ON Flight1.Destination = Flight2.OriginAND Flight1.Origin = 'LAX')WITH DATA

Origin Destination Origin Destination Origin Destination Origin Destination ------------------------------------ ----------------------------------------------------ATL BOS ATL BOS ATL BOS ATL BOS LAX BOSLAX BOSLAX BOSLAX BOSLAX ATL LAX ATL LAX ATL LAX ATL LAX SFO LAX SFO LAX SFO LAX SFO ORD BOS ORD BOS ORD BOS ORD BOS SFO ORD SFO ORD SFO ORD SFO ORD

Flight1

Origin Destination CostOrigin Destination CostOrigin Destination CostOrigin Destination Cost------------------------------------ ---------------------------------------------------- ------------------------ATL BOS 140ATL BOS 140ATL BOS 140ATL BOS 140LAX BOS 300LAX BOS 300LAX BOS 300LAX BOS 300LAX ATL 250LAX ATL 250LAX ATL 250LAX ATL 250LAX SFO 90LAX SFO 90LAX SFO 90LAX SFO 90ORD BOS 180ORD BOS 180ORD BOS 180ORD BOS 180SFO ORD 275SFO ORD 275SFO ORD 275SFO ORD 275

Flight2

Two rows into Flights_1Stop

Page 5: After completing this module, you will be able to ...dbmanagement.info/Books/MIX/Module03-Recursive_TeraData.pdf · ®Building Tables for Recursive Processing Suppose we want to find

® Querying Two Levels of Recursion

To show all flights with either no connections or only one connection, a union of the two tables is needed.

Show all flights with either no connections or one connection originating from LAX.

SELECT * FROM Flights WHERE origin = 'LAX'UNION ALLSELECT * FROM Flights_1Stop;

Origin Origin Origin Origin Destination CostDestination CostDestination CostDestination Cost------------------------------------ ---------------------------------------------------- ------------------------LAX BOS 300LAX BOS 300LAX BOS 300LAX BOS 300LAX SFO 90LAX SFO 90LAX SFO 90LAX SFO 90LAX ATL 250LAX ATL 250LAX ATL 250LAX ATL 250LAX BOS 390 LAX BOS 390 LAX BOS 390 LAX BOS 390 LAX ORD 365LAX ORD 365LAX ORD 365LAX ORD 365

(one stopover in Atlanta)(one stopover in San Francisco)

Page 6: After completing this module, you will be able to ...dbmanagement.info/Books/MIX/Module03-Recursive_TeraData.pdf · ®Building Tables for Recursive Processing Suppose we want to find

® Creating a “Two-Stopover” Table

Create a new table with all flight plans using two stopovers.

CREATE TABLE Flights_2Stops(Origin, Destination, Cost) AS (SELECT Flight1.Origin,

Flight2.Destination, Flight1.Cost + Flight2.Cost AS Price

FROM Flights_1Stop Flight1 JOIN Flights Flight2ON Flight1.Destination = Flight2.OriginWITH DATA;

Origin Origin Origin Origin Destination Destination Destination Destination ------------------------------------ ----------------------------------------------------LAX BOS LAX BOS LAX BOS LAX BOS LAX ORDLAX ORDLAX ORDLAX ORD

Flights_1Stop Flights

Origin Destination CostOrigin Destination CostOrigin Destination CostOrigin Destination Cost------------------------------------ ---------------------------------------------------- ------------------------ATL BOS 140ATL BOS 140ATL BOS 140ATL BOS 140LAX BOS 300LAX BOS 300LAX BOS 300LAX BOS 300LAX ATL 250LAX ATL 250LAX ATL 250LAX ATL 250LAX SFO 90LAX SFO 90LAX SFO 90LAX SFO 90ORD BOS 180ORD BOS 180ORD BOS 180ORD BOS 180SFO ORD 275SFO ORD 275SFO ORD 275SFO ORD 275

This row into Flights_2Stops

Page 7: After completing this module, you will be able to ...dbmanagement.info/Books/MIX/Module03-Recursive_TeraData.pdf · ®Building Tables for Recursive Processing Suppose we want to find

® Querying Three Levels of Recursion

Origin DestOrigin DestOrigin DestOrigin Dest------------------------------------ ----------------ATL BOS ATL BOS ATL BOS ATL BOS LAX BOSLAX BOSLAX BOSLAX BOSLAX ATL LAX ATL LAX ATL LAX ATL LAX SFO LAX SFO LAX SFO LAX SFO ORD BOS ORD BOS ORD BOS ORD BOS SFO ORD SFO ORD SFO ORD SFO ORD

Flights Table

Origin DestOrigin DestOrigin DestOrigin Dest------------------------------------ ----------------ATL BOS ATL BOS ATL BOS ATL BOS LAX BOS LAX BOS LAX BOS LAX BOS LAX ATL LAX ATL LAX ATL LAX ATL LAX SFO LAX SFO LAX SFO LAX SFO ORD BOS ORD BOS ORD BOS ORD BOS SFO ORD SFO ORD SFO ORD SFO ORD

Flights Table Repeated

Origin DestOrigin DestOrigin DestOrigin Dest------------------------------------ ----------------ATL BOS ATL BOS ATL BOS ATL BOS LAX BOS LAX BOS LAX BOS LAX BOS LAX ATL LAX ATL LAX ATL LAX ATL LAX SFO LAX SFO LAX SFO LAX SFO ORD BOS ORD BOS ORD BOS ORD BOS SFO ORD SFO ORD SFO ORD SFO ORD

Flights Table Repeated

SELECT origin, destFROM FlightsWHERE origin = ‘lax’;

CREATE TABLE Flight_a AS(SELECT f1.origin, f2.destFROM Flights f1, Flights f2WHERE f1.origin = 'lax'AND f1.dest = f2.origin)WITH DATA;

CREATE TABLE Flight_b AS(SELECT f1.origin, f2.destFROM Flight_a f1, Flights f2WHERE f1.dest = f2.origin)WITH DATA;

LAX BOS LAX BOS LAX BOS LAX BOS LAX ATL LAX ATL LAX ATL LAX ATL LAX SFO LAX SFO LAX SFO LAX SFO

Result

LAX BOS LAX BOS LAX BOS LAX BOS LAX ORD LAX ORD LAX ORD LAX ORD

Flight_a

LAX BOS LAX BOS LAX BOS LAX BOS

Flight_bUNION

ALLUNION

ALL

The approach shown below can be used to return all destinations leaving from LAX. This same logic can be used to understand recursive query logic.

Page 8: After completing this module, you will be able to ...dbmanagement.info/Books/MIX/Module03-Recursive_TeraData.pdf · ®Building Tables for Recursive Processing Suppose we want to find

® Recursive Query Logic

Notice that this encompasses all routes from LAX.All routes dead-end (none endlessly recurs).

LAX ���� BOSLAX ���� ATL ���� BOSLAX ���� SFO ���� ORD

Show all flights from LAX with up to two stopovers.

SELECT * FROM Flights WHERE origin = 'LAX'UNION ALLSELECT * FROM Flights_1StopUNION ALLSELECT * FROM Flights_2Stops;

Origin Destination CostOrigin Destination CostOrigin Destination CostOrigin Destination Cost------------------------------------ ------------------------------------------------ ------------------------

LAX BOS 300LAX BOS 300LAX BOS 300LAX BOS 300LAX SFO 90LAX SFO 90LAX SFO 90LAX SFO 90LAX ATL 250LAX ATL 250LAX ATL 250LAX ATL 250LAX BOS 390 (one stopover)LAX BOS 390 (one stopover)LAX BOS 390 (one stopover)LAX BOS 390 (one stopover)LAX ORD 365 (one stopover)LAX ORD 365 (one stopover)LAX ORD 365 (one stopover)LAX ORD 365 (one stopover)LAX BOS 545 (two stopovers)LAX BOS 545 (two stopovers)LAX BOS 545 (two stopovers)LAX BOS 545 (two stopovers)

Origin Destination CostOrigin Destination CostOrigin Destination CostOrigin Destination Cost------------------------------------ ---------------------------------------------------- ------------------------ATL BOS 140ATL BOS 140ATL BOS 140ATL BOS 140LAX BOS 300LAX BOS 300LAX BOS 300LAX BOS 300LAX ATL 250LAX ATL 250LAX ATL 250LAX ATL 250LAX SFO 90LAX SFO 90LAX SFO 90LAX SFO 90ORD BOS 180ORD BOS 180ORD BOS 180ORD BOS 180SFO ORD 275SFO ORD 275SFO ORD 275SFO ORD 275

Original Flights Table

Page 9: After completing this module, you will be able to ...dbmanagement.info/Books/MIX/Module03-Recursive_TeraData.pdf · ®Building Tables for Recursive Processing Suppose we want to find

® Recursive Query Example

We may use a recursive derived table to solve this problem with a single query. The keyword RECURSIVE states that the All_Trips is a 'recursively' derived table.

WITH RECURSIVE All_Trips(Origin, Destination, Cost, Depth) AS (SELECT Origin, Destination, Cost, 0FROM Flights WHERE Origin = 'LAX'UNION ALLSELECT All_Trips.Origin,

Flights.Destination,All_Trips.Cost + Flights.cost,All_Trips.Depth + 1

FROM All_Trips JOIN FlightsON All_Trips.Destination = Flights.Origin AND All_Trips.Depth < 3 )SELECT * FROM All_TripsORDER BY 4;

Origin Destination Cost DepthOrigin Destination Cost DepthOrigin Destination Cost DepthOrigin Destination Cost Depth---------------------------- ------------------------------------------------ ------------------------ ------------------------LAX BOS 300 0LAX BOS 300 0LAX BOS 300 0LAX BOS 300 0LAX SFO 90 0 LAX SFO 90 0 LAX SFO 90 0 LAX SFO 90 0 LAX ATL 250 0LAX ATL 250 0LAX ATL 250 0LAX ATL 250 0LAX BOS 390 1 LAX BOS 390 1 LAX BOS 390 1 LAX BOS 390 1 LAX ORD 365 1LAX ORD 365 1LAX ORD 365 1LAX ORD 365 1LAX BOS 545 2LAX BOS 545 2LAX BOS 545 2LAX BOS 545 2

Result

A variation of the WITH form for a derived table.

• Seed query.• Inserts initial rows into All_Trips only.

• Recursive portion of the query.• Inserts additional rows into All_Trips. • Only joined to the immediately preceding

inserted rows.

Prevents infinite recursion.In our example this condition is never reached.

The query selecting from the derived table.

Page 10: After completing this module, you will be able to ...dbmanagement.info/Books/MIX/Module03-Recursive_TeraData.pdf · ®Building Tables for Recursive Processing Suppose we want to find

® Analyzing the Results

Note that the origin, in our result, is always LAX.

The maximum depth of 2 was a result of all routes being exhausted.

A maximum depth of 3 would be possible if more stopovers existed.

As the result set, it is difficult to know how one gets from LAX to BOS where the depth is 2.

Origin Destination Cost DepthOrigin Destination Cost DepthOrigin Destination Cost DepthOrigin Destination Cost Depth---------------------------- ------------------------------------------------ ------------------------ ------------------------LAX BOS 300 0LAX BOS 300 0LAX BOS 300 0LAX BOS 300 0LAX SFO 90 0 LAX SFO 90 0 LAX SFO 90 0 LAX SFO 90 0 LAX ATL 250 0LAX ATL 250 0LAX ATL 250 0LAX ATL 250 0LAX BOS 390 1 LAX BOS 390 1 LAX BOS 390 1 LAX BOS 390 1 LAX ORD 365 1LAX ORD 365 1LAX ORD 365 1LAX ORD 365 1LAX BOS 545 2LAX BOS 545 2LAX BOS 545 2LAX BOS 545 2

Result

An additional route like the one below could cause infinite looping as shown.

Origin Destination Origin Destination Origin Destination Origin Destination ------------------------------------ ----------------------------------------------------ATL BOS ATL BOS ATL BOS ATL BOS LAX BOS LAX BOS LAX BOS LAX BOS LAX ATL LAX ATL LAX ATL LAX ATL LAX SFO LAX SFO LAX SFO LAX SFO SFO ORDSFO ORDSFO ORDSFO ORDORD BOSORD BOSORD BOSORD BOSBOS SFOBOS SFOBOS SFOBOS SFO

FlightsTable

LAX ���� SFO ���� ORD ���� BOS ���� SFO

Added route

Page 11: After completing this module, you will be able to ...dbmanagement.info/Books/MIX/Module03-Recursive_TeraData.pdf · ®Building Tables for Recursive Processing Suppose we want to find

® Greater Than Two-City Recursion

In the query:• SFO is the initial origin.• Infinite looping occurs.• The origin changes to reflect the continuing cities.• Due to the condition on the Depth column, the recursion stopped at a depth of 8 otherwise it would continue indefinitely.

Origin Destination DepthOrigin Destination DepthOrigin Destination DepthOrigin Destination Depth------------------------ -------------------------------------------- --------------------SFO ORD 0SFO ORD 0SFO ORD 0SFO ORD 0ORD BOS 1ORD BOS 1ORD BOS 1ORD BOS 1BOS SFO 2BOS SFO 2BOS SFO 2BOS SFO 2SFO ORD 3SFO ORD 3SFO ORD 3SFO ORD 3ORD BOS 4ORD BOS 4ORD BOS 4ORD BOS 4BOS SFO 5BOS SFO 5BOS SFO 5BOS SFO 5SFO ORD 6SFO ORD 6SFO ORD 6SFO ORD 6ORD BOS 7ORD BOS 7ORD BOS 7ORD BOS 7BOS SFO 8BOS SFO 8BOS SFO 8BOS SFO 8

Result

Origin Destination Origin Destination Origin Destination Origin Destination ------------------------------------ ----------------------------------------------------ATL BOS ATL BOS ATL BOS ATL BOS LAX BOS LAX BOS LAX BOS LAX BOS LAX ATL LAX ATL LAX ATL LAX ATL LAX SFO LAX SFO LAX SFO LAX SFO SFO ORD SFO ORD SFO ORD SFO ORD ORD BOSORD BOSORD BOSORD BOSBOS SFOBOS SFOBOS SFOBOS SFO

FlightsTable

Rows ofFocusWITH RECURSIVE All_Trips

(Origin, Destination, Depth) AS (SELECT Origin, Destination, 0FROM Flights WHERE Origin = 'SFO'UNION ALLSELECT flights.origin,

Flights.Destination,All_Trips.Depth + 1

FROM All_Trips INNER JOIN FlightsON All_Trips.Destination = Flights.Origin WHERE All_Trips.Origin <> Flights.DestinationAND All_Trips.Depth < 8 )SELECT * FROM All_TripsORDER BY 3, 1, 2;

Was All_Trips.Origin

Page 12: After completing this module, you will be able to ...dbmanagement.info/Books/MIX/Module03-Recursive_TeraData.pdf · ®Building Tables for Recursive Processing Suppose we want to find

® Two-City Chain Recursion

WITH RECURSIVE All_Trips(Origin, Destination, Depth) AS (SELECT Origin, Destination, 0FROM Flights WHERE Origin = 'SFO'UNION ALLSELECT flights.origin,

Flights.Destination,All_Trips.Depth + 1

FROM All_Trips INNER JOIN FlightsON All_Trips.Destination = Flights.Origin WHERE All_Trips.Depth < 4AND All_Trips.Origin <> Flights.Destination)SELECT * FROM All_TripsORDER BY 3, 1, 2;

Origin Destination Origin Destination Origin Destination Origin Destination ------------------------------------ ----------------------------------------------------ATL BOS ATL BOS ATL BOS ATL BOS LAX BOS LAX BOS LAX BOS LAX BOS LAX ATL LAX ATL LAX ATL LAX ATL LAX SFO LAX SFO LAX SFO LAX SFO SFO ORD SFO ORD SFO ORD SFO ORD ORD SFO ORD SFO ORD SFO ORD SFO

FlightsTable

For the query:• Note the chain: SFO ���� ORD ���� SFO.• Infinite looping occurs within 2 cities.• The origin changes to reflect the continuing cities.• The <> condition prevents the origin, in All_Trips,

from connecting to a city that returns back to itself, in the Flights table.

Origin Destination DepthOrigin Destination DepthOrigin Destination DepthOrigin Destination Depth------------------------ -------------------------------------------- --------------------SFO ORD 0SFO ORD 0SFO ORD 0SFO ORD 0ORD SFO 1ORD SFO 1ORD SFO 1ORD SFO 1SFO ORD 2SFO ORD 2SFO ORD 2SFO ORD 2ORD SFO 3ORD SFO 3ORD SFO 3ORD SFO 3SFO ORD 4SFO ORD 4SFO ORD 4SFO ORD 4

Result without condition

Origin Destination DepthOrigin Destination DepthOrigin Destination DepthOrigin Destination Depth------------------------ -------------------------------------------- --------------------SFO ORD 0SFO ORD 0SFO ORD 0SFO ORD 0

Result with condition

Note

Page 13: After completing this module, you will be able to ...dbmanagement.info/Books/MIX/Module03-Recursive_TeraData.pdf · ®Building Tables for Recursive Processing Suppose we want to find

® Creating Recursive Views

A recursive view may be created for referencing. A view definition is seen here based upon the previous queries.

REPLACE RECURSIVE VIEW All_Trips_View(Origin, Destination, Cost, Depth) AS(SELECT Origin, Destination, Cost, 0FROM Flights WHERE Origin = 'LAX'UNION ALLSELECT Flights.origin,

Flights.Destination,All_Trips_View.Cost + Flights.Cost,All_Trips_View.Depth + 1

FROM All_Trips_View, FlightsWHERE All_Trips_View.Destination = Flights.Origin AND All_Trips_View.Depth < 12AND All_Trips_View.Origin <> Flights.Destination);

In the structure:• Recursive references are to the view name.

• The seed query origin is fixed at LAX.

• The depth is fixed at some number.

Page 14: After completing this module, you will be able to ...dbmanagement.info/Books/MIX/Module03-Recursive_TeraData.pdf · ®Building Tables for Recursive Processing Suppose we want to find

® Using Recursive Views

REPLACE RECURSIVE VIEW All_Trips_View(Origin, Destination, Cost, Depth) AS(SELECT Origin, Destination, Cost, 0FROM Flights WHERE Origin = 'LAX'UNION ALLSELECT Flights.origin,

Flights.Destination,All_Trips_View.Cost + Flights.Cost,All_Trips_View.Depth + 1

FROM All_Trips_View, FlightsWHERE All_Trips_View.Destination = Flights.Origin AND All_Trips_View.Depth < 12AND All_Trips_View.Origin <> Flights.Destination);

SELECT Origin, Destination, DepthFROM All_Trips_ViewWHERE Origin = 'ORD'ORDER BY 3, 1, 2;

Origin Destination DepthOrigin Destination DepthOrigin Destination DepthOrigin Destination Depth------------------------ -------------------------------------------- --------------------ORD BOS 2ORD BOS 2ORD BOS 2ORD BOS 2

SELECT * FROM All_Trips_ViewWHERE Depth = 2ORDER BY 4, 1, 2;

Origin Destination Cost DepthOrigin Destination Cost DepthOrigin Destination Cost DepthOrigin Destination Cost Depth------------------------ -------------------------------------------- -------------------- --------------------ORD BOS 545 2ORD BOS 545 2ORD BOS 545 2ORD BOS 545 2

SELECT Origin, Destination, DepthFROM All_Trips_ViewWHERE Depth < 5ORDER BY 3, 1, 2;

Origin Destination DepthOrigin Destination DepthOrigin Destination DepthOrigin Destination Depth------------------------ -------------------------------------------- --------------------LAX ATL 0LAX ATL 0LAX ATL 0LAX ATL 0LAX BOS 0LAX BOS 0LAX BOS 0LAX BOS 0LAX SFO 0LAX SFO 0LAX SFO 0LAX SFO 0ATL BOS 1ATL BOS 1ATL BOS 1ATL BOS 1SFO ORD 1SFO ORD 1SFO ORD 1SFO ORD 1ORD BOS 2ORD BOS 2ORD BOS 2ORD BOS 2

Note theresults

Page 15: After completing this module, you will be able to ...dbmanagement.info/Books/MIX/Module03-Recursive_TeraData.pdf · ®Building Tables for Recursive Processing Suppose we want to find

® A Problem with This View?

The query below will only project the initial segments from Flights as they appear in the table, and not additional stopovers.

SELECT * FROM All_Trips_View WHERE ORIGIN = 'LAX' ORDER BY 1, 2;

Origin Destination Cost DepthOrigin Destination Cost DepthOrigin Destination Cost DepthOrigin Destination Cost Depth------------------------ -------------------------------------------- -------------------------------------------- --------------------LAX ATL 250 0LAX ATL 250 0LAX ATL 250 0LAX ATL 250 0LAX BOS 300 0LAX BOS 300 0LAX BOS 300 0LAX BOS 300 0LAX SFO 90 0LAX SFO 90 0LAX SFO 90 0LAX SFO 90 0

REPLACE RECURSIVE VIEW All_Trips_View(Origin, Destination, Cost, Depth) AS(SELECT Origin, Destination, Cost, 0FROM Flights UNION ALLSELECT Flights.origin,

Flights.Destination,All_Trips_View.Cost + Flights.Cost,All_Trips_View.Depth + 1

FROM All_Trips_View, FlightsWHERE All_Trips_View.Destination = Flights.Origin AND All_Trips_View.Depth < 12AND All_Trips_View.Origin <> Flights.Destination);

SELECT Origin, Destination, DepthFROM All_Trips_ViewWHERE Depth < 5ORDER BY 3, 1, 2;

Origin Destination DepthOrigin Destination DepthOrigin Destination DepthOrigin Destination Depth------------------------ -------------------------------------------- --------------------LAX ATL 0LAX ATL 0LAX ATL 0LAX ATL 0LAX BOS 0LAX BOS 0LAX BOS 0LAX BOS 0LAX SFO 0LAX SFO 0LAX SFO 0LAX SFO 0ATL BOS 1ATL BOS 1ATL BOS 1ATL BOS 1SFO ORD 1SFO ORD 1SFO ORD 1SFO ORD 1ORD BOS 2ORD BOS 2ORD BOS 2ORD BOS 2

Page 16: After completing this module, you will be able to ...dbmanagement.info/Books/MIX/Module03-Recursive_TeraData.pdf · ®Building Tables for Recursive Processing Suppose we want to find

® Problem Resolved?

REPLACE RECURSIVE VIEW All_Trips_View(Origin, Destination, Cost, Depth) AS(SELECT Origin, Destination, Cost, 0FROM Flights UNION ALLSELECT All_Trips_View.Origin,

Flights.Destination,All_Trips_View.Cost + Flights.Cost,All_Trips_View.Depth + 1

FROM All_Trips_View, FlightsWHERE All_Trips_View.Destination = Flights.Origin AND All_Trips_View.Depth < 12AND All_Trips_View.Origin <> Flights.Destination);

Here we are repopulating the recursive origin.

Notice how, now, we project all stopovers as well as the initial segments.

Origin Destination Cost DepthOrigin Destination Cost DepthOrigin Destination Cost DepthOrigin Destination Cost Depth------------------------ -------------------------------------------- -------------------------------------------- --------------------LAX ATL 250 0LAX ATL 250 0LAX ATL 250 0LAX ATL 250 0LAX BOS 545 2LAX BOS 545 2LAX BOS 545 2LAX BOS 545 2LAX BOS 390 1LAX BOS 390 1LAX BOS 390 1LAX BOS 390 1LAX BOS 545 2LAX BOS 545 2LAX BOS 545 2LAX BOS 545 2LAX BOS 300 0LAX BOS 300 0LAX BOS 300 0LAX BOS 300 0LAX CHI 365 1LAX CHI 365 1LAX CHI 365 1LAX CHI 365 1LAX ORD 365 1LAX ORD 365 1LAX ORD 365 1LAX ORD 365 1LAX SFO 90 0LAX SFO 90 0LAX SFO 90 0LAX SFO 90 0

SELECT * FROM All_Trips_View WHERE ORIGIN = 'LAX' ORDER BY 1, 2;

Page 17: After completing this module, you will be able to ...dbmanagement.info/Books/MIX/Module03-Recursive_TeraData.pdf · ®Building Tables for Recursive Processing Suppose we want to find

®

Recursive Queries and Parameterized Macros

REPLACE MACRO All_Trips_Macro (inorigin CHAR(3), indepth BYTEINT)AS(WITH RECURSIVE All_Trips(Origin, Destination, Cost, Depth) AS(SELECT Origin, Destination, Cost, 0FROM Flights WHERE Origin = :inoriginUNION ALLSELECT Flights.origin,

Flights.Destination,All_Trips.Cost + Flights.Cost,All_Trips.Depth + 1

FROM All_Trips, FlightsWHERE All_Trips.Destination = Flights.Origin AND All_Trips.Depth < :indepth AND All_Trips.Origin <> Flights.Destination)SELECT * FROM All_TripsORDER BY 4, 1, 2;);

Origin Destination Cost DepthOrigin Destination Cost DepthOrigin Destination Cost DepthOrigin Destination Cost Depth------------------------ -------------------------------------------- -------------------- --------------------ORD BOS 180 0ORD BOS 180 0ORD BOS 180 0ORD BOS 180 0

EXEC All_Trips_Macro ('ORD', 2);

Origin Destination Cost DepthOrigin Destination Cost DepthOrigin Destination Cost DepthOrigin Destination Cost Depth------------------------ -------------------------------------------- -------------------- --------------------SFO ORD 275 0SFO ORD 275 0SFO ORD 275 0SFO ORD 275 0ORD BOS 455 1ORD BOS 455 1ORD BOS 455 1ORD BOS 455 1

EXEC All_Trips_Macro ('SFO', 3);

Parameterized macros may be used to conditionally display results as well.

Page 18: After completing this module, you will be able to ...dbmanagement.info/Books/MIX/Module03-Recursive_TeraData.pdf · ®Building Tables for Recursive Processing Suppose we want to find

® Flattening-Out the Hierarchy

Origin DestTree depthOrigin DestTree depthOrigin DestTree depthOrigin DestTree depth------------------------ ---------------------------------------------------------------------------- --------------------LAX ATL 0LAX ATL 0LAX ATL 0LAX ATL 0LAX BOS 0LAX BOS 0LAX BOS 0LAX BOS 0LAX SFO 0LAX SFO 0LAX SFO 0LAX SFO 0LAX ATL BOS 1LAX ATL BOS 1LAX ATL BOS 1LAX ATL BOS 1LAX BOS DFW 1LAX BOS DFW 1LAX BOS DFW 1LAX BOS DFW 1LAX SFO DFW 1LAX SFO DFW 1LAX SFO DFW 1LAX SFO DFW 1LAX SFO ORD 1LAX SFO ORD 1LAX SFO ORD 1LAX SFO ORD 1LAX ATL BOS DFW 2LAX ATL BOS DFW 2LAX ATL BOS DFW 2LAX ATL BOS DFW 2LAX BOS DFW SFO 2LAX BOS DFW SFO 2LAX BOS DFW SFO 2LAX BOS DFW SFO 2LAX SFO DFW BOS 2LAX SFO DFW BOS 2LAX SFO DFW BOS 2LAX SFO DFW BOS 2LAX SFO ORD BOS 2LAX SFO ORD BOS 2LAX SFO ORD BOS 2LAX SFO ORD BOS 2LAX ATL BOS DFW SFO 3LAX ATL BOS DFW SFO 3LAX ATL BOS DFW SFO 3LAX ATL BOS DFW SFO 3LAX BOS DFW SFO ORD 3LAX BOS DFW SFO ORD 3LAX BOS DFW SFO ORD 3LAX BOS DFW SFO ORD 3LAX SFO ORD BOS DFW 3LAX SFO ORD BOS DFW 3LAX SFO ORD BOS DFW 3LAX SFO ORD BOS DFW 3LAX ATL BOS DFW SFO ORD 4LAX ATL BOS DFW SFO ORD 4LAX ATL BOS DFW SFO ORD 4LAX ATL BOS DFW SFO ORD 4

WITH RECURSIVE All_Trips(Origin, Dest, DestTree, depth ) AS (SELECT Origin, Destination,

CAST(Destination AS VARCHAR(1000)),0

FROM Flights WHERE Origin = 'lax'UNION ALLSELECT All_Trips.Origin,

Flights.Destination,TRIM(All_Trips.DestTree)||' '||TRIM(Flights.Destination)

AS newdest,depth + 1

FROM All_Trips INNER JOIN FlightsON All_Trips.Dest = Flights.Origin AND all_trips.origin <> Flights.DestinationAND POSITION(flights.destination IN all_trips.desttree) = 0AND All_Trips.Depth < 8 )SELECT origin, desttree, depth FROM All_TripsORDER BY 3, 2;

Eliminates Two-City Recursion

Eliminates any destination already appearing as a stopover.

This is an attempt at displaying the actual path from origin to final destination.

Page 19: After completing this module, you will be able to ...dbmanagement.info/Books/MIX/Module03-Recursive_TeraData.pdf · ®Building Tables for Recursive Processing Suppose we want to find

®

WITH Derived Table Form without Recursive Logic

Multiple elements allowed in WITH list

Previouslyonly a single WITH list was allowed in a WITH clause, as seen here:

WITH list1(x1,y1) AS (SELECT * FROM t1) SELECT * FROM list1 ORDER BY x1, y1;

Nowmultiple WITH lists are allowed in a single WITH clause, as seen here:

WITH list1(x1,y1) AS (SELECT * FROM t1),list2(x2,y2) AS (SELECT * FROM t2)

SELECT * FROM with1,with2 ORDER BY x1, y1;

Page 20: After completing this module, you will be able to ...dbmanagement.info/Books/MIX/Module03-Recursive_TeraData.pdf · ®Building Tables for Recursive Processing Suppose we want to find

®

WITH Derived Table Form without Recursive Logic (continued)

Any Number of WITH Expressions in a Single DML StatementThis applies to both WITH and WITH RECURSIVE statements.

Previouslyonly a single WITH expression was permitted in a DML statement, as seen here:

WITH RECURSIVE list1(x1,y1) AS (SELECT * FROM T1) SELECT * FROM list1;

Nowmultiple WITH expressions are allowed in a single DML statement, as seen here:

WITH RECURSIVE list1(x1,y1) AS (SELECT * FROM T1 UNION ALL SELECT x1,b1 FROM t1, list1 WHERE a1=x1),

RECURSIVE list 2(x2,y2) AS (SELECT * FROM t2 UNION ALL SELECT x2,b2 FROM t2, list2 WHERE a2=x2)SEL * FROM list1, list2;

Page 21: After completing this module, you will be able to ...dbmanagement.info/Books/MIX/Module03-Recursive_TeraData.pdf · ®Building Tables for Recursive Processing Suppose we want to find

®

WITH Derived Table Form without Recursive Logic (continued)

Multiple Non-Recursive and Recursive WITH lists in the Same QueryMultiple WITH lists with both recursive and non-recursive processing in the same query is now possible.

WITH RECURSIVE list1(x1,y1) AS (SELECT * FROM t1 UNION ALL SELECT x1,b1 FROM t1, list1 WHERE a1=x1),

list2(x2,y2) AS (SEL * FROM T2)

SEL * FROM list1,list2;

Page 22: After completing this module, you will be able to ...dbmanagement.info/Books/MIX/Module03-Recursive_TeraData.pdf · ®Building Tables for Recursive Processing Suppose we want to find

® Limitations and Restrictions

The only set operator that can appear within a WITH RECURSIVE clause is UNION ALL. The following set operators cannot appear within a WITH RECURSIVE clause:

• UNION• INTERSECT - INTERSECT ALL• EXCEPT - EXCEPT ALL• MINUS - MINUS ALL

The following elements cannot appear within a WITH or WITH RECURSIVE clause:• WITH or WITH RECURSIVE clause• TOP N operator• User-defined functions• Columns with a UDT data type

The following elements cannot appear within a recursive statement in a WITH RECURSIVE clause:

• NOT IN or NOT EXISTS logical predicate• Aggregate functions• Ordered analytical functions• GROUP BY clause• HAVING clause• DISTINCT clause• Subqueries• Derived tables

Page 23: After completing this module, you will be able to ...dbmanagement.info/Books/MIX/Module03-Recursive_TeraData.pdf · ®Building Tables for Recursive Processing Suppose we want to find

® Module 3: Summary

Recursive Queries:

• Provide a relational method for iteratively querying hierarchal structures.

• Are built on a form of derived table syntax.

• Involve a “seed” query and an “iterative” query that are connected with the set operator UNION ALL.

• Can be made into views.

• Can be incorporated into macros.

Page 24: After completing this module, you will be able to ...dbmanagement.info/Books/MIX/Module03-Recursive_TeraData.pdf · ®Building Tables for Recursive Processing Suppose we want to find

® Module 3: Review Questions

False – only the WITH form can be used.

True

False – the user must provide this capability

False – they may “dead-end” on their own

True

False – only the recursive view has a special syntax

True

True or False:

1. Recursive queries may be written using either form of derived table.

2. Only the most recently added rows are available to the iterative portion.

3. The mechanism to prevent infinite recursion is automatically provided.

4. Without preventing infinite recursion, all recursive queries can loop indefinitely.

5. The WITH form for derived tables may be either recursive or non-recursive.

6. Both views and macros require a special syntax structure when referencing recursive queries.

7. The recursive query syntax for macros requires a final SELECT to return the rows.

Page 25: After completing this module, you will be able to ...dbmanagement.info/Books/MIX/Module03-Recursive_TeraData.pdf · ®Building Tables for Recursive Processing Suppose we want to find

® Module 3: Lab Exercise

1) Write a recursive query against the Employee table that show the manager-to-employee-to-manager relationships beginning with manager 801.

Does this relationship “dead-end” or loop continuously?