{"id":4352,"date":"2024-01-22T16:16:38","date_gmt":"2024-01-22T15:16:38","guid":{"rendered":"https:\/\/www.skillup.cloud\/?p=4352"},"modified":"2024-02-11T16:23:33","modified_gmt":"2024-02-11T15:23:33","slug":"recursive-cte-come-concatenare-i-risultati-su-ununica-riga","status":"publish","type":"post","link":"https:\/\/www.skillup.cloud\/it\/recursive-cte-come-concatenare-i-risultati-su-ununica-riga\/","title":{"rendered":"Recursive CTE come concatenare i risultati su un&#8217;unica riga"},"content":{"rendered":"\n<p>Di seguito gli articoli della serie CTE (incluso questo corrente):<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><span style=\"text-decoration: underline\"> <a href=\"https:\/\/www.skillup.cloud\/it\/iseries-sql-cte-common-table-expressions-definizioni-e-utilizzo\/\" target=\"_blank\" rel=\"noreferrer noopener\">iSeries Sql &#8211; CTE Common Table Expressions &#8211; definizioni e utilizzo<\/a> <\/span><\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li><span style=\"text-decoration: underline\"> <a href=\"https:\/\/www.skillup.cloud\/it\/cte-ricorsive-leleganza-della-semplicita-in-sql-1\/\" target=\"_blank\" rel=\"noreferrer noopener\">CTE Ricorsive: L&#8217;Eleganza della Semplicit\u00e0 in SQL &#8211; 1<\/a> <\/span><\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li><span style=\"text-decoration: underline\"> <a href=\"https:\/\/www.skillup.cloud\/it\/cte-ricorsive-leleganza-della-semplicita-in-sql-2\/\" target=\"_blank\" rel=\"noreferrer noopener\">CTE Ricorsive: L&#8217;Eleganza della Semplicit\u00e0 in SQL &#8211; 2<\/a> <\/span><\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li><span style=\"text-decoration: underline\"> <a href=\"https:\/\/www.skillup.cloud\/it\/cte-ricorsive-leleganza-della-semplicita-in-sql-3\/\" target=\"_blank\" rel=\"noreferrer noopener\">CTE Ricorsive: L&#8217;Eleganza della Semplicit\u00e0 in SQL &#8211; 3<\/a><\/span><\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li><span style=\"text-decoration: underline\"> <a href=\"https:\/\/www.skillup.cloud\/it\/recursive-cte-come-concatenare-i-risultati-su-ununica-riga\/\" target=\"_blank\" rel=\"noreferrer noopener\">Recursive CTE come concatenare i risultati su un\u2019unica riga<\/a> <\/span><\/li>\n<\/ul>\n\n\n\n<p class=\"has-large-font-size\"><strong>Definizione del contesto<\/strong><\/p>\n\n\n\n<p>Supponiamo di avere una tabella che riporta i risultati delle elaborazioni notturne di interfacce, come da esempio seguente:<\/p>\n\n\n\n<div class=\"wp-block-columns\">\n<div class=\"wp-block-column\">\n<figure class=\"wp-block-table aligncenter\"><table><tbody><tr><td>INT<\/td><td>RESULT<\/td><\/tr><tr><td>0011<\/td><td> <\/td><\/tr><tr><td>0012<\/td><td> <\/td><\/tr><tr><td>0013<\/td><td> <\/td><\/tr><tr><td>0014<\/td><td>W<\/td><\/tr><tr><td>0015<\/td><td> <\/td><\/tr><tr><td>0016<\/td><td>W<\/td><\/tr><tr><td>0017<\/td><td> <\/td><\/tr><tr><td>0018<\/td><td> <\/td><\/tr><tr><td>0019<\/td><td> <\/td><\/tr><tr><td>0020<\/td><td>E<\/td><\/tr><tr><td>0023<\/td><td>E<\/td><\/tr><tr><td>0024<\/td><td>W<\/td><\/tr><\/tbody><\/table><\/figure>\n<\/div>\n\n\n\n<div class=\"wp-block-column\"><\/div>\n<\/div>\n\n\n\n<p>Il risultato di una elaborazione pu\u00f2 essere senza segnalazioni (spazio), con warning (\u201cW\u201d) o con errori (\u201cE\u201d).<\/p>\n\n\n\n<p>supponiamo di voler ottenere su una sola riga la sintesi dei risultati, riportando all&#8217;inizio le elaborazioni errate, poi quelle con warning e infine quelle senza segnalazioni, come nell&#8217;esempio seguente:<\/p>\n\n\n\n<div class=\"wp-block-columns\">\n<div class=\"wp-block-column\">\n<figure class=\"wp-block-table\"><table><tbody><tr><td>ROW_NUM<\/td><td>INT_LIST<\/td><\/tr><tr><td>12<\/td><td>0020E, 0023E , 0014W , 0016W , 0024W , 0011 , 0012 , 0013 , 0015 , 0017 , 0018 , 0019<\/td><\/tr><\/tbody><\/table><\/figure>\n<\/div>\n<\/div>\n\n\n\n<p>tutto questo richiede un programma o pu\u00f2 essere fatto elegantemente con un comando sql?<\/p>\n\n\n\n<p class=\"has-large-font-size\"><strong>Query<\/strong><\/p>\n\n\n\n<p>Si, con il seguente comando Sql si ottiene esattamente il risultato atteso:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">with -- Interface result\n     W1 (INT, RESULT) as (\n        values ('0011', ' '), ('0012', ' '), ('0013', ' '), ('0014', 'W'),\n               ('0015', ' '), ('0016', 'W'), ('0017', ' '), ('0018', ' '),\n               ('0019', ' '), ('0020', 'E'), ('0023', 'E'), ('0024', 'W')\n        ) -- select * from W1 order by 1;\n     -- assign progressive numeration (first E errors, then W warnings,\n     -- finally processing without reports\n   , W2 (INTR, ROW_NUM, RESULT) as (\n       select W1.INT concat result concat CAST(RPAD(' ', 399, ' ') AS CHAR(400)) INTR\n            , row_number() over ( partition by 'COMMON_VALUE'\n               order by case W1.result\n                        when 'E' then 1\n                        when 'W' then 2\n                        when ' ' then 3\n                        end ,\n                       W1.INT) ROW_NUM\n                      , W1.RESULT\n          from W1 order by  1) -- select trim(INTR) INTR, ROW_NUM, RESULT from W2;\n     -- recursive CTE (Common Table Expression)\n   , W3 (INTR, ROW_NUM, INT_LIST)\n     as (select BASE.INTR, BASE.ROW_NUM, trim(BASE.INTR)\n           from W2 BASE where BASE.ROW_NUM = 1    union all\n          select t1.INTR, t1.ROW_NUM, INT_LIST concat ', ' concat trim(t1.INTR) concat ' '\n            from W3 t0, W2 t1 where t0.ROW_NUM + 1 = t1.ROW_NUM\n         ) -- select trim(INTR) INTR, ROW_NUM, INT_LIST from W3;\nselect ROW_NUM, INT_LIST from W3 RQ\n where RQ.ROW_NUM = (select max(ROW_NUM) from W3);\n<\/pre>\n\n\n\n<p>Questa query, partendo da una tabella contenente il risultati di elaborazioni di interfacce (W1), produce come risultato una sola riga contenente il numero delle interfacce e l&#8217;elenco di ogni singola interfaccia riportando prima quelle con E errore, poi quelle con W warning e infine quelle senza segnalazioni.<\/p>\n\n\n\n<p class=\"has-large-font-size\"><strong>Descrizione dettagliata Query<\/strong><\/p>\n\n\n\n<p>Vediamo in dettaglio come \u00e8 composta l&#8217;istruzione Sql<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li class=\"has-medium-font-size\"><strong>CTE W1 (Risultato Interfacce)<\/strong>:<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Questa CTE \u00e8 una simulazione di una tabella che utilizza la clausola <strong>VALUES<\/strong>, che crea un insieme temporaneo di righe (<strong>INT, RESULT<\/strong>). Ogni riga rappresenta un identificatore di interfaccia (<strong>INT<\/strong>) e il relativo risultato (<strong>RESULT<\/strong>), dove il risultato potrebbe essere un errore (&#8216;E&#8217;), un avviso (&#8216;W&#8217;) o nessun problema (&#8216; &#8216;).<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li class=\"has-medium-font-size\"><strong>CTE W2 (Numerazione Progressiva):<\/strong><\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Questa CTE aggiunge un numero progressivo a ciascuna riga da <strong>W1<\/strong> utilizzando la funzione finestra <strong>ROW_NUMBER()<\/strong>. Questa numerazione \u00e8 partizionata in base a un valore costante (che di fatto significa nessun partizionamento poich\u00e9 tutte le righe avranno lo stesso &#8220;COMMON_VALUE&#8221;) e ordinata prima in base al tipo di risultato (&#8220;E&#8221;, quindi &#8220;W&#8221;, quindi &#8220;&#8221;) e quindi dall&#8217;identificatore di interfaccia <strong>INT<\/strong>.<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>L&#8217;istruzione <strong>SELECT<\/strong> concatena il valore <strong>INT<\/strong>, il <strong>RESULT<\/strong> e una stringa riempita a destra di 399 spazi convertiti in <strong>CHAR(400)<\/strong> per garantire che tutti i valori <strong>INTR<\/strong> abbiano una lunghezza uniforme.<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Questa numerazione ordinata aiuta nella successiva concatenazione degli identificatori di interfaccia nell&#8217;ordine desiderato.<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li class=\"has-medium-font-size\"><strong>CTE W3 (CTE Ricorsiva per Concatenazione):<\/strong><\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Questa CTE \u00e8 ricorsivo e crea una singola stringa (<strong>INT_LIST<\/strong>) contenente tutti gli identificatori di interfaccia, nell&#8217;ordine specificato da <strong>W2<\/strong>.<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Si inizia con il caso base in cui <strong>ROW_NUM<\/strong> \u00e8 1, selezionando il primo identificatore di interfaccia.<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>La parte ricorsiva unisce <strong>W3<\/strong> a <strong>W2<\/strong> a condizione che <strong>W3.ROW_NUM + 1 = W2.ROW_NUM<\/strong>, aggiungendo di fatto il successivo identificatore di interfaccia all&#8217;elenco (<strong>INT_LIST<\/strong>) per ogni riga successiva.<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>La query ricorsiva continua finch\u00e9 tutte le righe non vengono elaborate, creando un elenco cumulativo di identificatori di interfaccia.<\/li>\n<\/ul>\n\n\n\n<p class=\"has-medium-font-size\"><strong>Istruzione Select finale:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>L&#8217;istruzione <strong>SELECT<\/strong> finale recupera l&#8217;ultima riga da <strong>W3<\/strong>, che contiene l&#8217;elenco cumulativo di tutte le interfacce ordinate per tipo di risultato e <strong>INT<\/strong>. <strong>ROW_NUM<\/strong> in questo caso rappresenta il conteggio totale delle interfacce.<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Utilizza una sottoquery per trovare <strong>max(ROW_NUM)<\/strong> per garantire che venga selezionato solo l&#8217;elenco finale e completo.<\/li>\n<\/ul>\n\n\n\n<p class=\"has-medium-font-size\"><strong>In sintesi<\/strong><\/p>\n\n\n\n<p>In sintesi, la query \u00e8 progettata per creare un elenco ordinato di identificatori di interfaccia, dando priorit\u00e0 agli errori (&#8216;E&#8217;), quindi agli avvisi (&#8216;W&#8217;) e infine a quelli senza problemi (&#8216; &#8216;), e lo presenta come una singola stringa insieme al conteggio totale delle interfacce.<\/p>\n\n\n\n<p>L&#8217;utilizzo della funzione <strong>RPAD<\/strong> e il cast su <strong>CHAR(400)<\/strong> garantiscono che ciascun identificatore nell&#8217;elenco sia formattato in modo uniforme, il che \u00e8 particolarmente importante per il processo di concatenazione ricorsiva.<\/p>\n\n\n\n<p class=\"has-large-font-size\"><strong>Sguardo pi\u00f9 approfondito<\/strong><\/p>\n\n\n\n<p>Per capire meglio il funzionamento delle CTE Ricorsive proviamo a dare una sguardo pi\u00f9 approfondito ai singoli risultati delle CTE intermedie.<\/p>\n\n\n\n<p class=\"has-medium-font-size\"><strong>CTE W2 (Numerazione Progressiva)<\/strong><\/p>\n\n\n\n<p>Questa CTE aggiunge una numerazione progressiva in base al tipo di risultato (&#8220;E&#8221;, quindi &#8220;W&#8221;, quindi &#8220;&#8221;) e quindi dall&#8217;identificatore di interfaccia INT.<\/p>\n\n\n\n<p>Questa numerazione ordinata aiuta nella successiva concatenazione degli identificatori di interfaccia nell&#8217;ordine desiderato.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">select trim(INTR) INTR, ROW_NUM, RESULT from W2;<\/pre>\n\n\n\n<p><\/p>\n\n\n\n<div class=\"wp-block-columns\">\n<div class=\"wp-block-column\">\n<figure class=\"wp-block-table\"><table><tbody><tr><td>INTR<\/td><td>ROW_NUM<\/td><td>RESULT<\/td><\/tr><tr><td>0020E<\/td><td>1<\/td><td>E<\/td><\/tr><tr><td>0023E<\/td><td>2<\/td><td>E<\/td><\/tr><tr><td>0014W<\/td><td>3<\/td><td>W<\/td><\/tr><tr><td>0016W<\/td><td>4<\/td><td>W<\/td><\/tr><tr><td>0024W<\/td><td>5<\/td><td>W<\/td><\/tr><tr><td>0011<\/td><td>6<\/td><td> <\/td><\/tr><tr><td>0012<\/td><td>7<\/td><td> <\/td><\/tr><tr><td>0013<\/td><td>8<\/td><td> <\/td><\/tr><tr><td>0015<\/td><td>9<\/td><td> <\/td><\/tr><tr><td>0017<\/td><td>10<\/td><td> <\/td><\/tr><tr><td>0018<\/td><td>11<\/td><td> <\/td><\/tr><tr><td>0019<\/td><td>12<\/td><td> <\/td><\/tr><\/tbody><\/table><\/figure>\n<\/div>\n\n\n\n<div class=\"wp-block-column\"><\/div>\n<\/div>\n\n\n\n<p class=\"has-medium-font-size\"><strong>CTE W3 (CTE Ricorsiva per Concatenazione)<\/strong><\/p>\n\n\n\n<p>Questa CTE ricorsiva crea iterativamente (in modo ricorsivo) una&nbsp; stringa (INT_LIST) contenente tutti gli identificatori di interfaccia, nell&#8217;ordine specificato da W2.<\/p>\n\n\n\n<p>La query ricorsiva continua finch\u00e9 tutte le righe non vengono elaborate, creando un elenco cumulativo di identificatori di interfaccia.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">select trim(INTR) INTR, ROW_NUM, INT_LIST from W3;<\/pre>\n\n\n\n<div class=\"wp-block-columns\">\n<div class=\"wp-block-column\">\n<figure class=\"wp-block-table\"><table><tbody><tr><td>INTR<\/td><td>ROW_NUM<\/td><td>INT_LIST<\/td><\/tr><tr><td>0020E<\/td><td><\/td><td>0020E<\/td><\/tr><tr><td>0023E<\/td><td><\/td><td>0020E, 0023E <\/td><\/tr><tr><td>0014W<\/td><td><\/td><td>0020E, 0023E , 0014W <\/td><\/tr><tr><td>0016W<\/td><td><\/td><td>0020E, 0023E , 0014W , 0016W <\/td><\/tr><tr><td>0024W<\/td><td><\/td><td>0020E, 0023E , 0014W , 0016W , 0024W <\/td><\/tr><tr><td>0011<\/td><td><\/td><td>0020E, 0023E , 0014W , 0016W , 0024W , 0011 <\/td><\/tr><tr><td>0012<\/td><td><\/td><td>0020E, 0023E , 0014W , 0016W , 0024W , 0011 , 0012 <\/td><\/tr><tr><td>0013<\/td><td><\/td><td>0020E, 0023E , 0014W , 0016W , 0024W , 0011 , 0012 , 0013 <\/td><\/tr><tr><td>0015<\/td><td><\/td><td>0020E, 0023E , 0014W , 0016W , 0024W , 0011 , 0012 , 0013 , 0015 <\/td><\/tr><tr><td>0017<\/td><td><\/td><td>0020E, 0023E , 0014W , 0016W , 0024W , 0011 , 0012 , 0013 , 0015 , 0017 <\/td><\/tr><tr><td>0018<\/td><td><\/td><td>0020E, 0023E , 0014W , 0016W , 0024W , 0011 , 0012 , 0013 , 0015 , 0017 , 0018 <\/td><\/tr><tr><td>0019<\/td><td><\/td><td>0020E, 0023E , 0014W , 0016W , 0024W , 0011 , 0012 , 0013 , 0015 , 0017 , 0018 , 0019<\/td><\/tr><\/tbody><\/table><\/figure>\n<\/div>\n<\/div>\n\n\n\n<p>Come si pu\u00f2 vedere il risultato della query contiene tutte le righe delle varie iterazioni e quella che a noi interessa \u00e8 l&#8217;ultima, ovvero quella dell&#8217;ultimo ciclo di ricorsivit\u00e0, che viene estratta dalla successiva e ultima CTE.<\/p>\n\n\n\n<p class=\"has-medium-font-size\"><strong>Istruzione Select finale<\/strong><\/p>\n\n\n\n<p>Questa CTE finale recupera l&#8217;ultima riga da W3, che contiene l&#8217;elenco cumulativo di tutte le interfacce ordinate per tipo di risultato e INT. ROW_NUM in questo caso rappresenta il conteggio totale delle interfacce<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">select ROW_NUM, INT_LIST\n  from W3 RQ\n where RQ.ROW_NUM = (select max(ROW_NUM) from W3)\n<\/pre>\n\n\n\n<div class=\"wp-block-columns\">\n<div class=\"wp-block-column\">\n<figure class=\"wp-block-table\"><table><tbody><tr><td>ROW_NUM<\/td><td>INT_LIST<\/td><\/tr><tr><td>12<\/td><td>0020E, 0023E , 0014W , 0016W , 0024W , 0011 , 0012 , 0013 , 0015 , 0017 , 0018 , 0019<\/td><\/tr><\/tbody><\/table><\/figure>\n<\/div>\n<\/div>\n\n\n\n<p class=\"has-large-font-size\"><strong>Conclusioni<\/strong><\/p>\n\n\n\n<p>La query SQL illustrata utilizza Common Table Expression (CTE) per organizzare e processare i dati di interfaccia, creando una lista ordinata di identificatori di interfaccia con un conteggio totale. Prioritizzando prima gli errori (&#8216;E&#8217;), poi gli avvisi (&#8216;W&#8217;) e infine gli identificatori senza segnalazioni (&#8216; &#8216;), il risultato finale \u00e8 una singola riga che contiene il numero totale di interfacce e un elenco concatenato di ciascuna interfaccia, facilitando la revisione e l&#8217;analisi dei risultati del processo di interfaccia.<\/p>\n\n\n\n<p>Tenere presente, come sempre, che l\u2019implementazione e le funzionalit\u00e0 effettive potrebbero variare a seconda della versione del sistema operativo iSeries e del database DB2. \u00c8 sempre buona norma fare riferimento alla documentazione ufficiale IBM per avere informazioni pi\u00f9 precise e dettagliate<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Di seguito gli articoli della serie CTE (incluso questo corrente): Definizione del contesto Supponiamo di avere una tabella che riporta i risultati delle elaborazioni notturne di interfacce, come da esempio seguente: INT RESULT 0011 0012 0013 0014 W 0015 0016&#8230;<\/p>\n","protected":false},"author":3,"featured_media":4357,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"_kadence_starter_templates_imported_post":false,"_kad_post_transparent":"","_kad_post_title":"","_kad_post_layout":"","_kad_post_sidebar_id":"","_kad_post_content_style":"","_kad_post_vertical_padding":"","_kad_post_feature":"","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"_kad_post_classname":"","footnotes":""},"categories":[17,15,18],"tags":[124,128,46],"class_list":["post-4352","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-piu-in-profondita","category-gestire-as400-con-sql","category-tips-and-tricks","tag-cte-common-table-expression","tag-cte-ricorsive","tag-sql"],"_links":{"self":[{"href":"https:\/\/www.skillup.cloud\/it\/wp-json\/wp\/v2\/posts\/4352","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.skillup.cloud\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.skillup.cloud\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.skillup.cloud\/it\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/www.skillup.cloud\/it\/wp-json\/wp\/v2\/comments?post=4352"}],"version-history":[{"count":6,"href":"https:\/\/www.skillup.cloud\/it\/wp-json\/wp\/v2\/posts\/4352\/revisions"}],"predecessor-version":[{"id":4382,"href":"https:\/\/www.skillup.cloud\/it\/wp-json\/wp\/v2\/posts\/4352\/revisions\/4382"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.skillup.cloud\/it\/wp-json\/wp\/v2\/media\/4357"}],"wp:attachment":[{"href":"https:\/\/www.skillup.cloud\/it\/wp-json\/wp\/v2\/media?parent=4352"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.skillup.cloud\/it\/wp-json\/wp\/v2\/categories?post=4352"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.skillup.cloud\/it\/wp-json\/wp\/v2\/tags?post=4352"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}