q

Recursive WITH, part II: Hierarchical queries

articles: 

In my last post, I looked at using recursive WITH to implement simple recursive algorithms in SQL. One very common use of recursion is to traverse hierarchical data. I recently wrote a series of posts on hierarchical data, using Oracle’s CONNECT BY syntax and a fun example. In this post, I’ll be revisiting the same data using recursive WITH.

There are dozens of examples of hierarchical data, from the EMP table to the Windows Registry to binary trees, but I went with something more fun: the skeleton from the old song “Dem Dry Bones”.

Quote:
Toe bone connected to the foot bone
Foot bone connected to the heel bone
Heel bone connected to the ankle bone
Ankle bone connected to the shin bone
Shin bone connected to the knee bone
Knee bone connected to the thigh bone
Thigh bone connected to the hip bone
Hip bone connected to the back bone
Back bone connected to the shoulder bone
Shoulder bone connected to the neck bone
Neck bone connected to the head bone

Since every bone has only one ancestor, and there is a root bone with no ancestor, this is hierarchical data and we can stick it in a table and query it.

SELECT * FROM skeleton;
BONE                                     CONNECTED_TO_THE
---------------------------------------- ----------------------------------------
shoulder                                 neck
back                                     shoulder
hip                                      back
thigh                                    hip
knee                                     thigh
leg                                      knee
foot                                     heel
head
neck                                     head
toe                                      foot
arm                                      shoulder
wrist                                    arm
ankle                                    leg
heel                                     ankle
finger                                   wrist
a rib                                    back
b rib                                    back
c rib                                    back

You can see that I added some ribs and an arm to make the skeleton more complete!

Using Oracle’s CONNECT BY syntax:

SQL> col bone FOR a10
SQL> col connected_to_the FOR a9
SQL> col level FOR 99
SQL> col bone_tree FOR a27
SQL> col path FOR a65
 
SELECT bone, connected_to_the, level, 
lpad(' ',2*level, ' ') || bone AS bone_tree , 
ltrim(sys_connect_by_path(bone,'>'),'>') AS path
FROM skeleton
START WITH connected_to_the IS NULL
CONNECT BY prior bone=connected_to_the 
ORDER siblings BY 1

BONE       CONNECTED LEVEL BONE_TREE                   PATH
---------- --------- ----- --------------------------- -----------------------------------------------------------------
head                     1   head                      head
neck       head          2     neck                    head>neck
shoulder   neck          3       shoulder              head>neck>shoulder
arm        shoulder      4         arm                 head>neck>shoulder>arm
wrist      arm           5           wrist             head>neck>shoulder>arm>wrist
finger     wrist         6             finger          head>neck>shoulder>arm>wrist>finger
back       shoulder      4         back                head>neck>shoulder>back
a rib      back          5           a rib             head>neck>shoulder>back>a rib
b rib      back          5           b rib             head>neck>shoulder>back>b rib
c rib      back          5           c rib             head>neck>shoulder>back>c rib
hip        back          5           hip               head>neck>shoulder>back>hip
thigh      hip           6             thigh           head>neck>shoulder>back>hip>thigh
knee       thigh         7               knee          head>neck>shoulder>back>hip>thigh>knee
leg        knee          8                 leg         head>neck>shoulder>back>hip>thigh>knee>leg
ankle      leg           9                   ankle     head>neck>shoulder>back>hip>thigh>knee>leg>ankle
heel       ankle        10                     heel    head>neck>shoulder>back>hip>thigh>knee>leg>ankle>heel
foot       heel         11                       foot  head>neck>shoulder>back>hip>thigh>knee>leg>ankle>heel>foot
toe        foot         12                         toe head>neck>shoulder>back>hip>thigh>knee>leg>ankle>heel>foot>toe

The above CONNECT BY query uses the LEVEL pseudocolumn and the SYS_CONNECT_BY_PATH function. With recursive WITH, there’s no need for these built-ins because these values fall naturally out of the recursion.

Let’s start with the basic hierarchical query rewritten in recursive WITH.
The hierarchical relationship in our table is:
Parent(row.bone) = row.connected_to_the

WITH skellarchy (bone, parent) AS
 ( SELECT bone, connected_to_the FROM skeleton 
   WHERE bone = 'head'                         -- Start with the root
 UNION ALL
   SELECT s.bone, s.connected_to_the 
   FROM skeleton s, skellarchy r
   WHERE r.bone = s.connected_to_the           -- Parent(row.bone) = row.connected_to_the
 )
SELECT * FROM skellarchy;

BONE       PARENT
---------- ----------------------------------------
head
neck       head
shoulder   neck
back       shoulder
arm        shoulder
hip        back
wrist      arm
a rib      back
b rib      back
c rib      back
thigh      hip
finger     wrist
knee       thigh
leg        knee
ankle      leg
heel       ankle
foot       heel
toe        foot

Because we built up the SKELLARCHY table recursively, it’s easy to make an equivalent to the LEVEL pseudocolumn; it falls right out of the recursion:

WITH skellarchy (bone, parent, the_level) AS
 ( SELECT bone, connected_to_the, 0 FROM skeleton 
   WHERE bone = 'head'                         
 UNION ALL
   SELECT s.bone, s.connected_to_the , r.the_level + 1
   FROM skeleton s, skellarchy r
   WHERE r.bone = s.connected_to_the           
 )
SELECT * FROM skellarchy;

BONE       PARENT      THE_LEVEL
---------- ---------- ----------
head                           0
neck       head                1
shoulder   neck                2
back       shoulder            3
arm        shoulder            3
hip        back                4
wrist      arm                 4
a rib      back                4
b rib      back                4
c rib      back                4
thigh      hip                 5
finger     wrist               5
knee       thigh               6
leg        knee                7
ankle      leg                 8
heel       ankle               9
foot       heel               10
toe        foot               11

and it’s also easy to build up a path from root to the current node like the “SYS_CONNECT_BY_PATH” function does for CONNECT BY queries:

WITH skellarchy (bone, parent, the_level, the_path) AS
 ( SELECT bone, connected_to_the, 0, CAST(bone AS varchar2(4000)) FROM skeleton 
   WHERE bone = 'head'                         
 UNION ALL
   SELECT s.bone, s.connected_to_the , r.the_level + 1, r.the_path || '->' || s.bone
   FROM skeleton s, skellarchy r
   WHERE r.bone = s.connected_to_the           
 )
SELECT * FROM skellarchy;

BONE       PARENT     THE_LEVEL THE_PATH
---------- ---------- --------- --------------------------------------------------------------------------------
head                          0 head
neck       head               1 head->neck
shoulder   neck               2 head->neck->shoulder
back       shoulder           3 head->neck->shoulder->back
arm        shoulder           3 head->neck->shoulder->arm
hip        back               4 head->neck->shoulder->back->hip
wrist      arm                4 head->neck->shoulder->arm->wrist
a rib      back               4 head->neck->shoulder->back->a rib
b rib      back               4 head->neck->shoulder->back->b rib
c rib      back               4 head->neck->shoulder->back->c rib
thigh      hip                5 head->neck->shoulder->back->hip->thigh
finger     wrist              5 head->neck->shoulder->arm->wrist->finger
knee       thigh              6 head->neck->shoulder->back->hip->thigh->knee
leg        knee               7 head->neck->shoulder->back->hip->thigh->knee->leg
ankle      leg                8 head->neck->shoulder->back->hip->thigh->knee->leg->ankle
heel       ankle              9 head->neck->shoulder->back->hip->thigh->knee->leg->ankle->heel
foot       heel              10 head->neck->shoulder->back->hip->thigh->knee->leg->ankle->heel->foot
toe        foot              11 head->neck->shoulder->back->hip->thigh->knee->leg->ankle->heel->foot->toe

and we can use our generated the_level column to make a nice display just as we used the level pseudocolumn with CONNECT BY:

WITH skellarchy (bone, parent, the_level) AS
 ( SELECT bone, connected_to_the, 0  FROM skeleton 
   WHERE bone = 'head'                         
 UNION ALL
   SELECT s.bone, s.connected_to_the , r.the_level + 1
   FROM skeleton s, skellarchy r
   WHERE r.bone = s.connected_to_the           
 )
SELECT lpad(' ',2*the_level, ' ') || bone AS bone_tree FROM skellarchy;

BONE_TREE
---------------------------
head
  neck
    shoulder
      back
      arm
        hip
        wrist
        a rib
        b rib
        c rib
          thigh
          finger
            knee
              leg
                ankle
                  heel
                    foot
                      toe

Now, the bones are coming out in a bit of a funny order for a skeleton. Instead of this:

    shoulder
      back
      arm
        hip
        wrist
        a rib
        b rib
        c rib
          thigh
          finger

I want to see this:

    shoulder
      arm
        wrist
          finger
      back
        a rib
        b rib
        c rib
        hip
          thigh

The rows are coming out in BREADTH FIRST ordering – meaning all siblings of ‘shoulder’ are printed before any children of ‘shoulder’. But I want to see them in DEPTH FIRST: going from shoulder to finger before we start on the backbone.

WITH skellarchy (bone, parent, the_level) AS
 ( SELECT bone, connected_to_the, 0  FROM skeleton 
   WHERE bone = 'head'                         
 UNION ALL
   SELECT s.bone, s.connected_to_the , r.the_level + 1
   FROM skeleton s, skellarchy r
   WHERE r.bone = s.connected_to_the           
 )
SEARCH DEPTH FIRST BY bone SET bone_order
SELECT lpad(' ',2*the_level, ' ') || bone AS bone_tree FROM skellarchy
ORDER BY bone_order;

BONE_TREE
---------------------------
head
  neck
    shoulder
      arm
        wrist
          finger
      back
        a rib
        b rib
        c rib
        hip
          thigh
            knee
              leg
                ankle
                  heel
                    foot
                      toe

And now the result looks more like a proper skeleton.

Now on to cycles. A cycle is a loop in the hierarchical data: a row is its own ancestor. To put a cycle in the example data, I made the skeleton bend over and connect the head to the toe:

UPDATE skeleton SET connected_to_the='toe' WHERE bone='head';

And now if we try to run the query:

ERROR at line 2:
ORA-32044: cycle detected while executing recursive WITH query

With the CONNECT BY syntax, we can use CONNECT BY NOCYCLE to run a query even when cycles exist, and the pseudocolumn CONNECT_BY_IS_CYCLE to help detect cycles. For recursive WITH, Oracle provides a CYCLE clause, which is a bit more powerful as it allows us to name the column which is cycling.

WITH skellarchy (bone, parent, the_level) AS
 ( SELECT bone, connected_to_the, 0  FROM skeleton 
   WHERE bone = 'head'                         
 UNION ALL
   SELECT s.bone, s.connected_to_the , r.the_level + 1
   FROM skeleton s, skellarchy r
   WHERE r.bone = s.connected_to_the           
 )
SEARCH DEPTH FIRST BY bone SET bone_order
CYCLE bone SET is_a_cycle TO 'Y' DEFAULT 'N'
SELECT lpad(' ',2*the_level, ' ') || bone AS bone_tree, is_a_cycle FROM skellarchy
--where is_a_cycle='N'
ORDER BY bone_order;

BONE_TREE                                                    I
------------------------------------------------------------ -
head                                                         N
  neck                                                       N
    shoulder                                                 N
      arm                                                    N
        wrist                                                N
          finger                                             N
      back                                                   N
        a rib                                                N
        b rib                                                N
        c rib                                                N
        hip                                                  N
          thigh                                              N
            knee                                             N
              leg                                            N
                ankle                                        N
                  heel                                       N
                    foot                                     N
                      toe                                    N
                        head                                 Y

The query runs until the first cycle is detected, then stops.

The CONNECT BY syntax does provide a nice pseudocolumn, CONNECT_BY_ISLEAF, which is 1 when a row has no further children, 0 otherwise. In my next post, I’ll look at emulating this pseudocolumn with recursive WITH.


Republished with permission. Original URL: http://rdbms-insight.com/wp/?p=103




q

Svartzonker Signature series 8´6" 40-140g - Spin

Svartzonker is niet enkel een beroemde kunstaasbouwer, hij is ook een uitstekend hengelbouwer. We voelen ons vereerd om u een speciale roofvis serie aan te bieden waarvoor enkel uiterst lichte componenten gebruikt werden.




q

Reins 1,2" Rockvibe Shad

De Rockvibe Shad is hét succesnummer van Reins. Gevist met dropshot, een loodkopje (Aji-Meba Jig Head of Platon !!), texas rig, carolina rig of op een jigkop vangt men op zowel zoet als zoutwater.




q

Come migliorare il processo di acquisto

Sono fortunato. Negli ultimi anni ho avuto la possibilità di partecipare alla progettazione e realizzazione di alcuni tra gli e-commerce più importanti nati in Italia. È bello, interessante e istruttivo lavorare per un e-commerce, perché il sito non è fine … Continua a leggere

L'articolo Come migliorare il processo di acquisto proviene da Fucinaweb.





q

Quando un foglio volante è meglio di un’app

Perché realizzare un’applicazione mobile per un festival? Forse per permettere ai visitatori di accedere al calendario degli eventi senza stampare il programma. Magari per essere aggiornati sulle variazioni dell’ultimo minuto. Probabilmente per facilitare l’accesso ai luoghi degli incontri. O per … Continua a leggere

L'articolo Quando un foglio volante è meglio di un’app proviene da Fucinaweb.




q

Abu Musab al-Zarqawi is Dead Meat

At least he still has his head attached, which is more than we can say for his victims.

You live by Violence, You Die by Violence


Related links: current events, current affairs, terror, terrorism, terrorist





q

Es "grummelt" in der SPD wegen K-Frage

Die Union hat Merz, die Grünen Habeck, die SPD Scholz - doch spätestens mit dem Ampel-Aus fragt sich mancher in der Partei, ob man wirklich mit dem Kanzler wieder antreten sollte. Fraktionschef Mützenich bestätigt ein "Grummeln" in der SPD.




q

Earn Free CME's, CNEs, CEUs, CPE with "Explaining the Unexplained" CDC Video- Expires January 21, 2014.

This exciting session of Grand Rounds focused on rapid identification of emerging infectious diseases. As our world increases in interconnectivity of both technology and people, the rapid identification of emerging infectious diseases becomes more important for disease treatment, control, and prevention.Earn Free CME's, CNEs, CEUs, CPE with "Explaining the Unexplained" CDC Video- Expires January 21, 2014. 




q

2wd nv5600 swap questions

I have read through dozens of threads for nv5600 swaps in 4wd trucks but I have not found a single one on a 2wd, is there something that makes it not possible in 2wd? I can get a 2wd 3rd gen...



  • 1st Gen. Ram - All Topics


q

Gary Chew reviews "Made in Dagenham"

Rita O'Grady and husband Eddie work at Ford Motor in 1960s London. She's a good mother, wife, housekeeper, friend... and a totally uncompromising shop steward for a band of rogue unionist females who work for much lower pay than their male counterparts. With Sally Hawkins, Bob Hoskins, and Miranda Richardson. Now in limited release.




q

Gary Chew reviews "Country Strong"

Gwyneth Paltrow as country singing star Kelly Canter. No you're not having a Jack Daniels flashback of "Tender Mercies", "Crazy Heart" and "True Grit", though you wouldn't be far off if you did. Now playing.




q

Gary Chew reviews "Blue Valentine"

Two-track love story in which the now of it is shown alternately with its beginning six years before. Chew calls it raw, real, tender, touching, happy, goofy... and sad. A smart date movie for realists. Stars Ryan Gosling and Michelle Williams. Now in limited release.




q

Gary Chew reviews "The Company Men"

"Glengarry Glen Ross" lite, updated for our times? Chew explains. With Ben Affleck, Chris Cooper, Maria Bello, Rosemarie DeWitt and Kevin Costner. Now in limited release.




q

Gary Chew reviews "Kalamity"

Majoring in stream-of-consciousness with a minor in death-obsession are Nick Stahl and Jonathan Jackson. Alona Tal and Beau Garrett help the medicine go down. Now in limited release.




q

Gary Chew reviews "The Illusionist"

It's 1959. The career of the magician in this marvelous, artfully animated feature film is quickly slipping over the horizon. He is alone, but can still find joy in kindness to a young girl he meets along his tour. Now in limited release.




q

Gary Chew reviews "Barney's Version"

Barney Panofsky is a TV producer and thrice-married party dog whose life goes verkakte. From the book by Mordecai Richler, the movie is set in the same cynical Canadian milieu established in Richler's earlier opus, "The Apprenticeship of Duddy Kravitz". Starring Paul Giamatti, with Minnie Driver, Rosamund Pike and Dustin Hoffman. Now in limited release.




q

Gary Chew reviews "The King's Speech"

The best movie from 2010 that Chew has seen in 2011... and eligible for the Best Picture Oscar this weekend. With Colin Firth, Geoffrey Rush, Helena Bonham Carter. Now playing.




q

The entire 1949 "Tulsa" movie on YouTube

When discussion turned to this epic starring Robert Preston, Chill Wills and Susan Hayward, Lazzaro found the whole thing on YouTube, and posted it in GroupBlog 321.




q

Gary Chew reviews "Paul" movie

A diminutive other-world alien gets encountered in the vicinity of Area 51 by two comic book geeks from England named Graeme and Clive. With Simon Pegg, Nick Frost, Jane Lynch, Jeffrey Tambor, Jason Bateman, Sigourney Weaver, Kristen Wiig, Tulsa's Bill Hader, John Carroll Lynch and Seth Rogen. Opens 3/18.




q

Gary Chew's movie quiz question

...is still outstanding. More about the "fabulous" prizes in GroupBlog 323.




q

Gary Chew reviews "Source Code"

Jake Gyllenhaal "Quantum Leaps" multiple times into an explosive trainwreck of the very recent past. Will he foil the mad bomber and find true love? The answer will become available to you on April Fool's Day.




q

The "Make Me Smile" show, 70s Tulsa Cable

A kids' program filmed in the basement of the Tulsa library whose theme song was "Make Me Smile". Dave McFadden was part of the show. He tells us about it and has a great promo photo. In GroupBlog 324.




q

Gary Chew reviews "Hanna"

Chew: "One could almost imagine that 'Hanna' begins where Cormac McCarthy's 'The Road' leaves off, except that the child with the father, both trekking through a post apocalyptic world, is not male, but female." Stars Saoirse Ronan, Eric Bana and Cate Blanchett. Opens April 8.




q

Chew reviews "Born to Be Wild" in 3D

IMAX 3D documentary about animals whose destiny is to exist in the wild, narrated by Morgan Freeman. Opens wide on April 8.




q

Gary Chew reviews "The Conspirator"

Robert Redford's relevant, thought-provoking film about the immediate aftermath of the assassination of President Abraham Lincoln. Stars James McAvoy, Robin Wright and Tom Wilkinson. Opens wide on April 15.




q

Gary Chew reviews "Water for Elephants"

Take a heaping helping of 1956's "Trapeze", mix in mid-30s Gable/Harlow movies, and add a soupcon of 1955's "Picnic", and you have something much like this new movie starring Robert Pattinson and Reese Witherspoon. Opens wide on April 23.




q

Gary Chew reviews "In A Better World"

Best Foreign Language Oscar winner for 2011. Danish director Susanne Bier and screenwriter Anders Thomas Jensen tell a stoic story about two upper-middle class Danish families, one just stricken with the natural death of the mother, the other slipping from estrangement into divorce. Each has a boy about 11 years old. Chew calls it grounded and uplifting, despite the strife, pain and disillusionment. Now in limited release, opens at Tulsa's Circle Cinema on 5/20.




q

Gary Chew reviews "Everything Must Go"

Will Ferrell is Nick, recently-fired regional VP of sales and backsliding alcoholic whose wife put his ass out in the grass. Rebecca Hall is Samantha, newly moved in across the street from Nick, pregnant and awaiting her husband's arrival to settle down to Arizona living. Laura Dern is Delilah, divorced former high school bud of Nick's, living in the area with her two kids. She and Nick haven't seen each since graduation. Opens at the Circle Cinema 5/13.




q

Gary Chew reviews "The Beaver"

Depressing, maudlin, creepier than "Mulholland Drive", but then again, Mel Gibson's character is seen talking to Jon Stewart with a stuffed beaver on his fist. Opens wide on May 20.




q

Gary Chew reviews "The Tree of Life"

Director Terrence Malick creates a realistic, but dreamlike tale, spinning from a routine life in Waco of the mid-Fifties to an urban present. Stars Brad Pitt and Sean Penn. In limited release May 27.




q

Leon Meier of "Shock Theatre"

Tulsa World story about retiring Brook Plaza barber Joe Reeves also features Leon Meier, who was "Hornstaff" on KOTV's 1950s horror movie show, "Shock Theatre". Story link and TTM "Shock Theatre" link in GroupBlog 327.




q

Gary Chew reviews "Midnight in Paris"

Woody Allen's new movie has Owen Wilson escaping his Hollywood present to early 20th Century Paris. A better time to live a life? With Rachel McAdams, now in limited release.




q

Gary Chew reviews "The Art of Getting By"

A tender, funny, coming-of-age yarn starring Freddie Highmore, Emma Roberts, Alicia Silverstone, Blair Underwood and Rita Wilson. Opens wide June 17.




q

Gary Chew reviews "Beginners"

Thirtysomething Oliver has just struggled his way past the event of the death of his eccentric mother. Not long after, his father announces: "I'm gay. And I've known it since before I married your mother." Stars Ewan McGregor and Christopher Plummer. Now in limited release.




q

Downtown Tulsa mystery diner quiz

Lazzaro submits an interior black and white photo of a diner which he will later identify with a shot of its business sign. In GroupBlog 328.




q

Gary Chew reviews "Horrible Bosses"

Plenty of laughs in this R-rated, extremely rude flick. Jason Bateman, Jason Sedeikus and Charlie Day are the aggrieved employees; Kevin Spacey, Colin Farrell and Jennifer Aniston are the horrible bosses. Opens wide Friday.




q

Gary Chew reviews "Friends with Benefits"

Gary Chew says FwB is really, really quite bad. But on the brighter side, it does feature Mila Kunis, Justin Timberlake, Woody Harrelson, Patricia Clarkson, Jenna Elfman and Richard Jenkins. Opens wide July 22.




q

Gary Chew reviews "Cowboys and Aliens"

Daniel Craig can't remember a thing when he wakes up in the Old West with a high-tech wristwatch thing attached to his arm. It's just what he'll need in this new-fashioned shoot-em-up with Harrison Ford and Olivia Wilde. Opens wide July 29.




q

Gary Chew reviews "Another Earth"

A double of Earth has been behind the sun for eons... until now. A young woman's life changes at the instant its synchronicity with Earth One is broken. Starring Brit Marling and William Mapother, coming soon to a theater near you.




q

Gary Chew reviews "One Day"

Emma and Dexter are college students who have an overnight fling just after graduation. They decide to meet up same time each year to see what's up with their friendship. With Jim Sturgess, Anne Hathaway and Patricia Clarkson. Opens wide Friday.




q

Gary Chew reviews "The Debt"

In the 1990s, three former Mossad agents try to work out what went wrong during their mid-60s mission in East Berlin to kidnap and bring to justice a very evil man. With Helen Mirren, Tom Wilkinson and Jessica Chastain. Now playing.




q

"Rumble Fish" event downtown tonight

Coppola's 1983 "Rumble Fish", based on S.E. Hinton's novel, was filmed in downtown Tulsa. The characters in the film hang out at Benny's Billiards. A photo/video art installation will be unveiled at 8 pm tonight at 13 East Brady (site of Benny's). Circle Cinema is showing the movie at 11:00 pm. Meet and Greet at Caz's Chowhouse starting at 6 pm. More at the link.




q

Gary Chew reviews "Higher Ground"

Actress Vera Farmiga makes her directorial debut in this contemporary story of a thirtysomething married woman and mother dealing with her faith. Now playing.




q

Gary Chew reviews "Straw Dogs"

Remake of Sam Peckinpah's 1971 classic is important, and in its strange and unsettling way, approaches cinematic art. Stars James Marsden and Kate Bosworth. Now playing.




q

Gary Chew reviews "Moneyball"

This low-key Brad Pitt vehicle, a cerebral baseball story, may not be to everyone's taste, including Oscar's. Also stars Jonah Hill and Philip Seymour Hoffman. Opens today.




q

Gary Chew reviews "What's Your Number?"

Pretty entertaining for a templated rom-com. The number in question is how many persons with whom one has shared intimate moments. Stars Anna Faris, Chris Evans, Ari Graynor and Blythe Danner. Opens today.




q

Gary Chew reviews "The Ides of March"

Stellar cast in a drama portraying an Ohio presidential primary scheduled on what proved to be a bad hair day for Julius Caesar. With Ryan Gosling, George Clooney, Philip Seymour Hoffman, Paul Giamatti, Evan Rachel Wood, Marisa Tomei, Jeffrey Wright and Gregory Itzin. Opens today.