{"id":348,"date":"2021-04-25T18:39:16","date_gmt":"2021-04-25T18:39:16","guid":{"rendered":"https:\/\/maboc.nl\/?p=348"},"modified":"2021-04-25T18:39:16","modified_gmt":"2021-04-25T18:39:16","slug":"recursive-sql-in-db2","status":"publish","type":"post","link":"https:\/\/maboc.nl\/?p=348","title":{"rendered":"Recursive SQL in DB2"},"content":{"rendered":"<p><b>Problem<\/b><br \/>\nPlaying around in DB2 I wanted to know how to create a hiearchical query. This because I wanted to create view for explain plans, a bit resembling the explain plans which oracle provides.<\/p>\n<p>First step is understanding how to make the recursive SQL&#8217;s<\/p>\n<p><b>The setup:<\/b><\/p>\n<pre>\r\ndrop table relations;\r\n\r\ncreate table relations (id int, parent int);\r\n\r\ninsert into relations values(0,NULL);\r\ninsert into relations values(1,0);\r\ninsert into relations values(2,1);\r\ninsert into relations values(3,1);\r\ninsert into relations values(4,3);\r\ninsert into relations values(5,0);\r\ninsert into relations values(6,5);\r\ninsert into relations values(7,5);\r\ninsert into relations values(8,6);\r\ninsert into relations values(9,7);\r\ninsert into relations values(10,0);\r\ninsert into relations values(11,1);\r\n\r\ncommit;\r\n<\/pre>\n<p>Just to be sure,it looks like:<\/p>\n<pre>\r\nID          PARENT     \r\n----------- -----------\r\n          0           -\r\n          1           0\r\n          2           1\r\n          3           1\r\n          4           3\r\n          5           0\r\n          6           5\r\n          7           5\r\n          8           6\r\n          9           7\r\n         10           0\r\n         11           1\r\n<\/pre>\n<p>What I would like to see is something resembling following:<\/p>\n<pre>\r\nID   Parent\r\n0    -\r\n1      0\r\n2         1\r\n3         1\r\n4            3\r\n11        1\r\n5      0\r\n6         5\r\n8            6\r\n7         5\r\n9            7\r\n10     0         \r\n<\/pre>\n<p><b>First try: (Recursive) Common Table Expressions (r)CTE<\/b><br \/>\nDB2 has a nice way to have recursion in r(CTE) let&#8217;s see if I can get that working:<\/p>\n<pre>\r\nwith recur(id, parent, level) as\r\n  (\r\n    select rel.id id, rel.parent parent, 1 level \r\n    from   relations rel\r\n    where  rel.id=0\r\n    union all\r\n    select rel.id, rel.parent, rec.level+1 \r\n    from   recur rec,\r\n           relations rel\r\n    where  rec.id=rel.parent\r\n    and    rec.level<10\r\n  )\r\nselect id, \r\n       cast(lpad(parent, level*2, ' ') as varchar(20)) parent,\r\n       level \r\nfrom   recur;\r\n<\/pre>\n<p>This gives me the following result:<\/p>\n<pre>\r\nID          PARENT               LEVEL      \r\n----------- -------------------- -----------\r\n          0 -                              1\r\n          1    0                           2\r\n          5    0                           2\r\n         10    0                           2\r\n          2      1                         3\r\n          3      1                         3\r\n         11      1                         3\r\n          6      5                         3\r\n          7      5                         3\r\n          4        3                       4\r\n          8        6                       4\r\n          9        7                       4\r\n<\/pre>\n<p>This is somewhat resembling what I want. However, the query shows the rows all per level. After some searchinf I came to know that this is calles \"Search Breadth First\", what I need is \"Search Dept First\".<\/p>\n<p>Tried a lot of things but to no avail.<br \/>\nOn the net I came across the \"Search Dept First\" clause. This should then look like:<\/p>\n<pre>\r\nwith recur(id, parent, level) as\r\n  (\r\n    select rel.id id, rel.parent parent, 1 level \r\n    from   relations rel\r\n    where  rel.id=0\r\n    union all\r\n    select rel.id, rel.parent, rec.level+1 \r\n    from   recur rec,\r\n           relations rel\r\n    where  rec.id=rel.parent\r\n    and    rec.level<10\r\n  ) search depth first by parent set ordering\r\nselect id, \r\n       cast(lpad(parent, level*2, ' ') as varchar(20)) parent,\r\n       level \r\nfrom   recur\r\norder by ordering;\r\n<\/pre>\n<p>But ...NO....No luck there.<\/p>\n<p><b>Second try: Hiearchical SQL<\/b><br \/>\nAnother approach is using tha naticve hiearchical capabilities from the SQL implemantation:<\/p>\n<pre>\r\nselect id, lpad(parent, level*2, ' ') parent, level\r\nfrom   relations\r\nstart with id=0\r\nconnect by prior id=parent;\r\n<\/pre>\n<p>This didn't work at first. We first need to tell DB2 that it can use also these type of features:<\/p>\n<pre>\r\ndb2set DB2_COMPATIBILITY_VECTOR=08\r\ndb2stop\r\ndb2start\r\n<\/pre>\n<p>Since I'm on my development environment, I can stop and start the database whenever it suits me \ud83d\ude42<\/p>\n<p>Following output was generated by running this query:<\/p>\n<pre>\r\nID          PARENT           LEVEL      \r\n----------- ---------------- -----------\r\n          0 -                          1\r\n          1    0                       2\r\n          2      1                     3\r\n          3      1                     3\r\n          4        3                   4\r\n         11      1                     3\r\n          5    0                       2\r\n          6      5                     3\r\n          8        6                   4\r\n          7      5                     3\r\n          9        7                   4\r\n         10    0                       2\r\n<\/pre>\n<p>Exactly what I want. So at least we have a solution.<\/p>\n<p><b>(r)CTE revisited<\/b><br \/>\nI could not let go of the idea of CTE's so I posted on stackoverflow.com: <a href=\"https:\/\/stackoverflow.com\/questions\/67253826\/db2-search-depth-first-syntax-error\" rel=\"noopener\" target=\"_blank\">Question<\/a>.<\/p>\n<p>\"The Impaler\" came up with the following:<\/p>\n<pre>\r\nwith\r\nn (id, parent, lvl, ordering) as (\r\n  select id, parent, 1, lpad(id, 3, '0') || lpad('', 30, ' ')\r\n  from relations\r\n  where parent is null\r\n union all\r\n  select r.id, r.parent, n.lvl + 1, trim(n.ordering) || '\/' || lpad(r.id, 3, '0')\r\n  from n, relations r where r.parent = n.id\r\n)\r\nselect id, lpad(parent, lvl * 2, ' ') as parent, lvl, ordering\r\nfrom n\r\norder by ordering;\r\n<\/pre>\n<p>Which delivers:<\/p>\n<pre>\r\nID          PARENT               LVL         ORDERING                         \r\n----------- -------------------- ----------- ----------------------\r\n          0 -                              1 000                              \r\n          1    0                           2 000\/001\r\n          2      1                         3 000\/001\/002\r\n          3      1                         3 000\/001\/003      \r\n          4        3                       4 000\/001\/003\/004\r\n         11      1                         3 000\/001\/011\r\n          5    0                           2 000\/005        \r\n          6      5                         3 000\/005\/006\r\n          8        6                       4 000\/005\/006\/008\r\n          7      5                         3 000\/005\/007\r\n          9        7                       4 000\/005\/007\/009\r\n         10    0                           2 000\/010\r\n<\/pre>\n<p>Hehe that works like a charm!!!<br \/>\nThank you<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Problem Playing around in DB2 I wanted to know how to create a hiearchical query. This because I wanted to create view for explain plans, a bit resembling the explain plans which oracle provides. First step is understanding how to make the recursive SQL&#8217;s The setup: drop table relations; create table relations (id int, parent [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[64,49],"tags":[67,68,65,66,14],"class_list":["post-348","post","type-post","status-publish","format-standard","hentry","category-db2","category-sql","tag-common-table-expression","tag-cte","tag-db2","tag-recursion","tag-sql"],"_links":{"self":[{"href":"https:\/\/maboc.nl\/index.php?rest_route=\/wp\/v2\/posts\/348","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/maboc.nl\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/maboc.nl\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/maboc.nl\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/maboc.nl\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=348"}],"version-history":[{"count":6,"href":"https:\/\/maboc.nl\/index.php?rest_route=\/wp\/v2\/posts\/348\/revisions"}],"predecessor-version":[{"id":354,"href":"https:\/\/maboc.nl\/index.php?rest_route=\/wp\/v2\/posts\/348\/revisions\/354"}],"wp:attachment":[{"href":"https:\/\/maboc.nl\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=348"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/maboc.nl\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=348"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/maboc.nl\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=348"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}