<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Applied I - Medium]]></title>
        <description><![CDATA[it’s all about IBM I - Medium]]></description>
        <link>https://medium.com/applied-i?source=rss----1242cf7f716b---4</link>
        <image>
            <url>https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png</url>
            <title>Applied I - Medium</title>
            <link>https://medium.com/applied-i?source=rss----1242cf7f716b---4</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Wed, 11 Nov 2026 04:41:25 GMT</lastBuildDate>
        <atom:link href="https://medium.com/feed/applied-i" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[DB2 SQL JOINS]]></title>
            <link>https://medium.com/applied-i/db2-sql-joins-a6b205e8b0f?source=rss----1242cf7f716b---4</link>
            <guid isPermaLink="false">https://medium.com/p/a6b205e8b0f</guid>
            <category><![CDATA[db2]]></category>
            <category><![CDATA[sql-joins]]></category>
            <category><![CDATA[ibm-i-series]]></category>
            <category><![CDATA[ibm-i]]></category>
            <category><![CDATA[sql]]></category>
            <dc:creator><![CDATA[Sumit goyal]]></dc:creator>
            <pubDate>Wed, 26 May 2021 04:42:57 GMT</pubDate>
            <atom:updated>2021-05-26T04:27:30.777Z</atom:updated>
            <content:encoded><![CDATA[<p>SQL JOINS allows you to combine records for multiple tables based on some condition. This condition, in most cases, is “common value(s)” between tables needed to join. But there are options for more conditions. If you have worked on DB2 JOIN LOGICAL FILE, it has almost the same concept as SQL JOINS, but SQL JOINS give you more options and are very easy to use.</p><p>Type of SQL JOINS:</p><ol><li>Inner Join</li><li>Outer Join</li></ol><ul><li>Left Outer join</li><li>Right Outer join</li><li>FULL Outer join</li></ul><p>3. Exception Join</p><ul><li>Left Exception join</li><li>Right Exception join</li></ul><p>4. Cross Join</p><h4>Sample Data</h4><p>To understand joins, we are going to use straightforward data in 3 tables.</p><p>Table 1: SQLTEST1</p><pre>CREATE TABLE SQLTEST1 (file_key for keyf char(10),file_dob for dobf date)</pre><pre>INSERT INTO SQLTEST1 values(&#39;01&#39;,&#39;1999-10-10&#39;),(&#39;02&#39;,&#39;2000-10-10&#39;),(&#39;03&#39;,&#39;2001-11-11&#39;),(&#39;06&#39;,&#39;2016-12-12&#39;)</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*9Hg7gDUg8TYktlx45qND2A.png" /><figcaption>SQLTEST1</figcaption></figure><p>Table 2 : SQLTEST2</p><pre>CREATE TABLE SQLTEST2 ( file_key for keyf char(10), file_name for namef char(20))</pre><pre>INSERT INTO SQLTEST2 values(&#39;01&#39;,&#39;SUMIT&#39;),(&#39;02&#39;,&#39;AMIT&#39;),(&#39;04&#39;,&#39;AMAN&#39;),(&#39;05&#39;,&#39;RAM&#39;)</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*fwJXnxjZqJKTEdBfZ4F5sA.png" /><figcaption>SQLTEST2</figcaption></figure><p>Table 3 : SQLTEST3</p><pre>CREATE TABLE SQLTEST3 (file_key for keyf char(10) ,  file_last for lastf char(20))</pre><pre>INSERT INTO SQLTEST3 values(&#39;01&#39;,&#39;Goyal&#39;),(&#39;05&#39;,&#39;Kumar&#39;),(&#39;06&#39;,&#39;Gupta&#39;)</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*AjtzCLHnwvoQJu_xlOtMmg.png" /><figcaption>SQLTEST2</figcaption></figure><h3>INNER JOIN</h3><p>INNER Join returns records that are common in all tables based on the given join condition. There are two ways to write INNER Join.</p><ol><li><strong>With JOIN keyword</strong></li></ol><pre>SELECT * FROM SQLTEST1 a JOIN SQLTEST2 b ON a.keyf= b.keyf</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*0OJ-kPY2U8pWeDnx_D3LyQ.png" /></figure><p>You can JOIN more than two tables:</p><pre>SELECT * FROM SQLTEST1 a JOIN SQLTEST2 b ON a.keyf = b.keyf JOIN SQLTEST3 c ON b.keyf =c.keyf</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*p1Hx94kh7X1LDx_q4lPDpg.png" /></figure><p>2.<strong> Without JOIN keyword</strong></p><pre>SELECT * FROM SQLTEST1 AS a , SQLTEST2 AS b WHERE a.keyf= b.keyf</pre><p>This is the same as:</p><pre>SELECT * FROM SQLTEST1 a JOIN SQLTEST2 b ON a.keyf= b.keyf</pre><ol><li>JOIN keyword is replaced with &quot;,&quot;</li><li>ON keyword is replaced with WHERE clause.</li><li>ON must be used instead of “WHERE” to specify the join condition when the JOIN keyword is used.</li></ol><h3>OUTER JOIN</h3><p>SQL OUTER Join gives</p><ul><li>All data from the PRIMARY table with matching date from the SECONDARY table(s) appended to it.</li><li>If no matching data found in the SECONDARY table(s) for the join condition, a NULL value will be used to fill that space.</li></ul><p>There are 3 types of OUTER JOIN.</p><ol><li><strong>LEFT OUTER JOIN or LEFT JOIN (Yes, we can omit word OUTER)</strong></li></ol><ul><li>The “LEFT OUTER JOIN” table on the leftmost side of the “JOIN keyword” is considered as the “PRIMARY table.”</li><li>table(s) on the JOIN keyword&#39;s right side is considered the SECONDARY table(s).</li></ul><pre>SELECT * FROM SQLTEST1 a LEFT JOIN SQLTEST2 b ON a.keyf= b.keyf</pre><ol><li>ON keyword specify the join condition.</li><li>All data from SQLTEST1(LEFT Table) with matching date from SQLTEST2(RIGHT table) appended to it.</li><li>If no matching data found in the SQLTEST2 table for the join condition, a NULL value will be used to fill that space.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*J-IjP2O5qz3-m9BfES1LBA.png" /><figcaption><strong>LEFT OUTER JOIN or LEFT JOIN</strong></figcaption></figure><p><strong><em>When there are more than two tables in OUTER JOIN, the ON keyword defines which table is primary to which table.</em></strong></p><pre>SELECT * FROM SQLTEST1 a    <br>	LEFT JOIN SQLTEST2 b ON a.keyf = b.keyf                   <br>        LEFT JOIN SQLTEST3 c ON <strong><em>a.keyf = c.keyf</em></strong></pre><p>There are 2 LEFT JOINS in this query.</p><ol><li>Join 1 &gt; Primary Table : SQLTEST1 Secondary Table : SQLTEST2 based on “ON a.keyf = b.keyf”</li><li>Join 2 &gt; Primary Table : SQLTEST1 Secondary Table : SQLTEST3 based on “ON a.keyf = c.keyf”</li></ol><p>So the output will be</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*D-89Ydwtc3f2D2dykTxOOg.png" /><figcaption><strong>LEFT OUTER JOIN or LEFT JOIN</strong></figcaption></figure><p>Now change last ON condition from “<em>ON a.keyf = c.keyf</em>” to “<em>ON b.keyf = c.keyf</em>”</p><pre>SELECT * FROM SQLTEST1 a    <br>	LEFT JOIN SQLTEST2 b ON a.keyf = b.keyf                   <br>        LEFT JOIN SQLTEST3 c ON <strong><em>b.keyf = c.keyf</em></strong></pre><p>Again there are 2 LEFT JOINS in this query.</p><ol><li>Join 1 &gt; Primary Table : SQLTEST1 Secondary Table : SQLTEST2 based on “ON a.keyf = b.keyf”</li><li>Join 2 &gt; <strong>Primary Table : SQLTEST2</strong> Secondary Table : SQLTEST3 based on “ON b.keyf = c.keyf”. Now SQL will try to match table SQLTEST2(not table SQLTEST1) and table SQLTEST3.</li></ol><p>Now the output will be changed to</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ZRYx_NPZ3VxlwA7qLLLefA.png" /><figcaption><strong>LEFT OUTER JOIN or LEFT JOIN</strong></figcaption></figure><p>2. <strong>RIGHT OUTER JOIN or RIGHT JOIN</strong></p><p>The concept of the RIGHT OUTER JOIN is the same as of LEFT OUTER JOIN. In the case of RIGHT OUTER JOIN right-most table of JOIN keyword, the only difference is PRIMARY TABLE.</p><pre>SELECT * FROM SQLTEST1 a RIGHT JOIN SQLTEST2 b ON a.keyf= b.keyf</pre><ul><li>ON keyword specify the join condition.</li><li>All data from SQLTEST2 (RIGHT Table) with matching date from SQLTEST1 (LEFT table) appended to it.</li><li>If no matching data found in the SQLTEST1 table for the join condition, a NULL value will be used to fill that space.</li></ul><p>3. <strong>FULL OUTER JOIN or FULL JOIN</strong></p><p>FULL JOIN is a combination of LEFT JOIN and RIGHT JOIN. It will get you all records from all tables based on the join conditions.</p><pre>SELECT * FROM SQLTEST1  a FULL JOIN SQLTEST2 b on a.keyf= b.keyf</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*NC8YAtN3Mgsyj6UFzbOjsQ.png" /><figcaption><strong>FULL OUTER JOIN or FULL JOIN</strong></figcaption></figure><h3>EXCEPTION JOIN</h3><p>Here is how SQL EXCEPTION JOIN works.</p><ul><li>It returns rows from the PRIMARY table that don’t have a match in any of the SECONDARY tables.</li><li>Columns that come from the SECONDARY table(s) will always have a null value.</li></ul><p>DB2 SQL supports 2 types of EXCEPTION JOINs:</p><p><strong>1. Left Exception Join</strong></p><ul><li>The table on the left side of the JOIN keyword will be considered as the PRIMARY table.</li><li>Table(s) on the JOIN keyword&#39;s right side will be considered the SECONDARY table.</li></ul><pre>SELECT* FROM SQLTEST1  a LEFT EXCEPTION JOIN SQLTEST2 b on a.keyf= b.keyf</pre><p>In this case:</p><ul><li>SQLTEST1 is the PRIMARY table.</li><li>SQLTEST2 is the SECONDARY table.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Ctk89lg_xjKuJ4c5n_7yAA.png" /><figcaption><strong>Left Exception Join</strong></figcaption></figure><p><strong>2. Right Exception Join</strong></p><ul><li>The table on the right side of the JOIN keyword will be considered as the PRIMARY table.</li><li>Table(s) on the JOIN keyword&#39;s left side will be considered as the SECONDARY table.</li></ul><pre>SELECT* FROM SQLTEST1  a RIGHT EXCEPTION JOIN SQLTEST2 b on a.keyf= b.keyf</pre><p>In this case:</p><ul><li>SQLTEST2 is the PRIMARY table.</li><li>SQLTEST1 is the SECONDARY table.</li></ul><h3>CROSS JOIN</h3><p>SQL CROSS JOIN returns every possible combination of rows from every table being joined(This is also called Cartesian product).</p><pre>SELECT * FROM SQLTEST1 a CROSS JOIN SQLTEST2 b</pre><p>Point to note: There is no &quot;ON&quot; keyword that means no join condition.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*63jrs6WxwfvsE2FmVD3bnA.png" /><figcaption>Cross join</figcaption></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a6b205e8b0f" width="1" height="1" alt=""><hr><p><a href="https://medium.com/applied-i/db2-sql-joins-a6b205e8b0f">DB2 SQL JOINS</a> was originally published in <a href="https://medium.com/applied-i">Applied I</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[DB2 SQL TABLE EXPRESSION]]></title>
            <link>https://medium.com/applied-i/db2-sql-table-expression-52586724b71b?source=rss----1242cf7f716b---4</link>
            <guid isPermaLink="false">https://medium.com/p/52586724b71b</guid>
            <category><![CDATA[common-table-expressions]]></category>
            <category><![CDATA[db2]]></category>
            <category><![CDATA[ibm-i]]></category>
            <category><![CDATA[ibm-i-series]]></category>
            <category><![CDATA[sql]]></category>
            <dc:creator><![CDATA[Sumit goyal]]></dc:creator>
            <pubDate>Wed, 26 May 2021 04:42:52 GMT</pubDate>
            <atom:updated>2021-05-26T03:42:40.893Z</atom:updated>
            <content:encoded><![CDATA[<p>SQL TABLE EXPRESSION gives you the power to create a temporary table inside a query. The life of this temporary table is only inside that query. As soon as the query is completed temporary table will vanish.</p><p>This is a handy and powerful concept and can help you solve complex issues with straightforward queries.</p><p>There are 2 types of TABLE EXPRESSIONs in DB2 SQL</p><ol><li>Nested table expressions(also called Derived tables)</li><li>Common table expressions</li></ol><h3>NESTED TABLE EXPRESSION</h3><p>Nested table expressions(NTE) (also called derived tables)</p><p>The basic syntax of the SQL SELECT statement is like</p><pre>SELECT * FROM table-name</pre><ol><li>Nested table expressions give you the option to replace “table-name”(after FROM clause) with “(SELECT-statement),” which acts as a temporary table.</li><li>To use this Temporary table in the query, we must give this Temporary table a name (<a href="https://www-01.ibm.com/support/knowledgecenter/SSEPEK_10.0.0/com.ibm.db2z10.doc.sqlref/src/tpc/db2z_correlationnames.dita">correlation name</a>).</li></ol><pre>SELECT * FROM <strong>(SELECT MAX(SALARY) AS MAXSAL, WORKDEPT FROM EMPLOYEE E1 GROUP BY WORKDEPT) AS T2</strong></pre><p>In the above query, “(SELECT MAX(SALARY) AS MAXSAL, WORKDEPT FROM CORPDATA.EMPLOYEE E1 GROUP BY WORKDEPT) AS T2” is NTE with correlation name T2.</p><p>You can use other tables with NTE in the same query.</p><pre>SELECT MGRNO, T1.DEPTNO, MAXSAL FROM DEPARTMENT T1,<br>		<strong>(SELECT MAX(SALARY) AS MAXSAL, WORKDEPT FROM EMPLOYEE E1 GROUP BY WORKDEPT) T2</strong><br>	WHERE T1.DEPTNO = T2.WORKDEPT ORDER BY DEPTNO</pre><p>In the same way above, you can use multiple NTEs in a single query.</p><p>Someone can easy confuse NTE with <a href="http://qsys400.com/db2-sql-subqueries/">SubQueries </a>as both follow almost the same syntax.<strong> The point to remember here is NTE replaces “Table” in FROM clause where SubQueries give the option to use a query in WHERE and HAVING clauses.</strong></p><h3>COMMON TABLE EXPRESSION (CTE)</h3><ol><li>Unlike <a href="http://qsys400.com/db2-sql-table-expression-nte/">NESTED TABLE EXPRESSION</a>, CTE is not specified in FROM clause of the query.</li><li>But CTE is specified before the full-select in a SELECT statement using WITH keyword.</li><li>A single query can contain multiple CTEs, but the keyword WITH is used only once.</li><li>Inside query, the CTE table is treated as any other normal table.</li><li>By default, CTE uses column names from the query, it is driven from(Or the system-generated name in case of some SQL Function like SUM() is used), But there is an option to rename CTE table columns.</li></ol><pre><strong>WITH AVSAL AS<br>     (SELECT WORKDEPT, AVG(SALARY) as AVGSAL <br>        FROM EMPLOYE  GROUP BY WORKDEPT)</strong><br>SELECT WORKDEPT, MAX(AVGSAL) AS MAXAVGSAL <br>FROM AVSAL GROUP BY WORKDEPT;</pre><p>The above code “WITH AVSAL AS (SELECT WORKDEPT, AVG(SALARY) as AVGSAL FROM EMPLOYEE GROUP BY WORKDEPT)” defines a CTE with the name AVSAL means now there is a temporary table with the name AVSAL available to this query.</p><p>In the next line, “SELECT WORKDEPT, MAX(AVGSAL) AS MAXAVGSAL FROM AVSAL GROUP BY DEPT,” a select statement is used to get data from CTE table AVSAL like any other table.</p><p>Rename columns for CTE</p><pre><strong>WITH AVSAL(DEPARTMENT,AVGSALARY) AS<br>(SELECT   WORKDEPT, AVG(SALARY) as AVGSAL  <br>FROM  EMPLOYE  GROUP BY WORKDEPT)</strong><br>SELECT DEPARTMENT, MAX(AVGSALARY) AS MAXAVGSAL <br>FROM AVSAL GROUP BY DEPARTMENT;</pre><p>The above query “WITH AVSAL(DEPARTMENT, AVGSALARY) AS” renames the CTE table AVSAL’s columns to DEPARTMENT and AVGSALARY.</p><p>Using Multiple CTEs in a Single Query</p><p>This is a sample of a complex query where Multiple CTE tables are being used in combination with SQL JOINS. For multiple CTEs in a single query, there is only a single WITH clause.</p><pre>WITH Ctable1 AS<br>(SELECT C1Field1, <br>row_number() over(partition by C1Field2) as rowNbr<br>FROM SampleTable1  WHERE C1Field5 = &quot;XYZ&quot; ), <br>		<br>Ctable2 AS<br>(SELECT  SampleTable1.* , <br>row_number() over(order by C2Field3 desc) as rowNbr<br>FROM SampleTable2 <br>      INNER JOIN SampleTable3 ON C2Field = SampleTable3.C3Field<br>WHERE C2Field5 &lt;= &quot;ABC&quot;)</pre><pre>SELECT * FROM Ctable1 t1 <br>       FULL JOIN Ctable2 t2 ON t1.C1Field1 = t2.C2Field1 <br>WHERE t1.rowNbr = 1 OR t2.rowNbr = 1</pre><p>In the Above two temporary tables Ctable1 and Ctable2. Ctable1 is created using a simple select statement with OLAP function row_number. Ctable2 is created by <a href="http://qsys400.com/db2-sql-joins-inner-join/">joining</a> two tables SampleTable2 and SampleTable3.</p><p>And finally, “SELECT statement,” which joins Ctable1 and Ctable2 using <a href="http://qsys400.com/db2-sql-joins-outer-join/">FULL JOIN</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=52586724b71b" width="1" height="1" alt=""><hr><p><a href="https://medium.com/applied-i/db2-sql-table-expression-52586724b71b">DB2 SQL TABLE EXPRESSION</a> was originally published in <a href="https://medium.com/applied-i">Applied I</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[DB2 SQL OLAP PART 5: GROUPING SETS]]></title>
            <link>https://medium.com/applied-i/db2-sql-olap-part-5-grouping-sets-9472c76cd29a?source=rss----1242cf7f716b---4</link>
            <guid isPermaLink="false">https://medium.com/p/9472c76cd29a</guid>
            <category><![CDATA[ibm-i-series]]></category>
            <category><![CDATA[db2]]></category>
            <category><![CDATA[sql]]></category>
            <category><![CDATA[olap]]></category>
            <category><![CDATA[ibm-i]]></category>
            <dc:creator><![CDATA[Sumit goyal]]></dc:creator>
            <pubDate>Wed, 26 May 2021 04:42:47 GMT</pubDate>
            <atom:updated>2021-05-26T03:29:10.346Z</atom:updated>
            <content:encoded><![CDATA[<p>With the “GROUP BY” clause, SQL accepts a single set of columns, and based on that set final result is produced.</p><p>Something like this</p><pre>SELECT country,city,sum(population) from Census GROUP By <strong><em>COUNTRY, CITY</em></strong></pre><p>“GROUP By <strong>COUNTRY, CITY”</strong> defines a set with values COUNTRY and CITY. Only one list can be specified for a query.</p><p>If you need more than one set of values, you need to total population by COUNTRY/CITY and CITY/ZIP in the same query. The Standard “GROUP BY” clause does not give the option to use multiple sets of columns.</p><h3>GROUPING SETS</h3><ol><li>This is another extension to the “GROUP BY” clause,</li><li>This allows using multiple column sets with the “GROUP BY” clause within a single SQL Query,</li></ol><pre>SELECT country,city,zip,sum(population) from Census <br>GROUP By <strong><em>GROUPING SETS</em></strong>((COUNTRY,CITY),(CITY,ZIP))</pre><ol><li>This is running</li></ol><pre>SELECT country,city,zip,sum(population) from Census GROUP By  COUNTRY,CITY</pre><p>-AND-</p><pre>SELECT country,city,zip,sum(population) from Census GROUP By CITY,ZIP</pre><p>and <strong>then union the result.</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*VFn1K-0jsXKL3Hvj4bNoKQ.png" /></figure><h3>GROUPING SETS with <a href="http://qsys400.com/db2-sql-olap-rollup-and/">ROLLUP and CUBE</a>.</h3><p>You can combine GROUPING SETS with ROLLUP and CUBE to create more complex combinations.</p><pre>SELECT country,city,zip,sum(population) from Census <br>GROUP By <strong><em>GROUPING SETS</em></strong>((COUNTRY,CITY), <strong><em>ROLLUP</em></strong>(CITY,ZIP))</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*yw9UngN4BZBmK1GY9L50Xw.png" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9472c76cd29a" width="1" height="1" alt=""><hr><p><a href="https://medium.com/applied-i/db2-sql-olap-part-5-grouping-sets-9472c76cd29a">DB2 SQL OLAP PART 5: GROUPING SETS</a> was originally published in <a href="https://medium.com/applied-i">Applied I</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[DB2 SQL OLAP PART 4: ROLLUP and CUBE]]></title>
            <link>https://medium.com/applied-i/db2-sql-olap-part-4-rollup-and-cube-27ab8c1fc167?source=rss----1242cf7f716b---4</link>
            <guid isPermaLink="false">https://medium.com/p/27ab8c1fc167</guid>
            <category><![CDATA[sql]]></category>
            <category><![CDATA[ibm-i]]></category>
            <category><![CDATA[ibm-i-series]]></category>
            <category><![CDATA[db2]]></category>
            <category><![CDATA[olap]]></category>
            <dc:creator><![CDATA[Sumit goyal]]></dc:creator>
            <pubDate>Wed, 26 May 2021 04:42:40 GMT</pubDate>
            <atom:updated>2021-05-24T20:13:15.190Z</atom:updated>
            <content:encoded><![CDATA[<p>ROLLUP and CUBE both are extensions for the “GROUP BY” clause.</p><p>Let&#39;s take an example of a “Census” table that keeps a record of the population by COUNTRY, CITY, ZIP, and POPULATION (in millions) like this.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*UxMLsmhvEFrYhcx3VzsgGQ.png" /></figure><p><strong>Task 1</strong>: Get a report for the total population by each COUNTRY and CITY.</p><pre>SELECT COUNTRY,CITY,<strong>SUM(POPULATION)</strong> as POPULATION from Census <br><strong>GROUP BY  COUNTRY,CITY</strong></pre><p>A simple “GROUP BY” with SUM() will work perfectly.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ALVrA_TtfAcoDnD2croB3g.png" /></figure><p><strong>Task 2</strong>: In the last report, add a <strong>new row for sub-total</strong> by country and then a <strong>new row for the total</strong> population.</p><ol><li>This may be possible use some very complex SQL query by not by Simple “GROUP BY.”</li></ol><h3>ROLLUP</h3><ol><li>With the ROLLUP booster, “GROUP BY” will create sub-total and final total with a minor change in a previous SQL query.</li></ol><pre>select COUNTRY,CITY,SUM(POPULATION) as total from Census <br>GROUP BY <strong>ROLLUP</strong> (COUNTRY,CITY)</pre><p>These are the Steps this query will follow</p><ol><li>Aggregate (in this case using SUM() function) by</li></ol><ul><li>COUNTRY and CITY</li><li>COUNTRY and <strong>NULL</strong> [ kind of SUB TOTAL]</li><li><strong>NULL</strong> and <strong>NULL </strong>[ kind of FINAL TOTAL]</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*0uqrWZUpcJfERjzAOlqzGA.png" /></figure><p>If you want all sub-total and Final total at the bottom of the report, add an “ORDER BY” clause to the query.</p><pre>select COUNTRY,CITY,SUM(POPULATION) as total from Census <br>GROUP BY ROLLUP (COUNTRY,CITY) <strong><em>ORDER BY CITY</em></strong></pre><ol><li>ORDER BY CITY will push the NULL CITY to the bottom of the result.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*6J7UUOrY0jA3iXpfRmHxtw.png" /></figure><h3>CUBE</h3><ol><li>Same as ROLLUP, CUBE is also an extension to the “GROUP BY” clause.</li><li>Consider CUBE as like: CUBE = ROLLUP + MORE LEVEL OF TOTAL</li></ol><pre>select COUNTRY,CITY,SUM(POPULATION) as total from Census <br>GROUP BY CUBE (COUNTRY,CITY)</pre><p>Aggregate (in this case using SUM() function) by [1,2,3 are same as ROLLUP]</p><ol><li>COUNTRY and CITY</li><li>COUNTRY and <strong>NULL</strong> [ kind of SUB TOTAL]</li><li><strong>NULL</strong> and <strong>NULL </strong>[ kind of FINAL TOTAL]</li><li><strong><em>NULL and CITY [ New to CUBE]</em></strong></li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2Uvs0Th04pkH2P5IiWMRDA.png" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=27ab8c1fc167" width="1" height="1" alt=""><hr><p><a href="https://medium.com/applied-i/db2-sql-olap-part-4-rollup-and-cube-27ab8c1fc167">DB2 SQL OLAP PART 4: ROLLUP and CUBE</a> was originally published in <a href="https://medium.com/applied-i">Applied I</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[DB2 SQL OLAP PART 3: RANK and DENSE_RANK]]></title>
            <link>https://medium.com/applied-i/db2-sql-olap-part-3-rank-and-dense-rank-1edc82053abe?source=rss----1242cf7f716b---4</link>
            <guid isPermaLink="false">https://medium.com/p/1edc82053abe</guid>
            <category><![CDATA[sql]]></category>
            <category><![CDATA[olap]]></category>
            <category><![CDATA[ibm-i]]></category>
            <category><![CDATA[db2]]></category>
            <category><![CDATA[ibm-i-series]]></category>
            <dc:creator><![CDATA[Sumit goyal]]></dc:creator>
            <pubDate>Wed, 26 May 2021 04:42:32 GMT</pubDate>
            <atom:updated>2021-05-24T19:58:37.104Z</atom:updated>
            <content:encoded><![CDATA[<p>To understand RANK and DENSE_RANK functions, let&#39;s examine how participants are ranked in an exam?</p><ol><li>Participant(s) with the highest marks got the 1st rank.</li><li>Participant(s) with the 2nd highest marks got the 2nd rank and so on.</li></ol><p>Here is a sample table with participant names with marks</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*c3S-Ql55T3dNZDAbRM7t_w.png" /></figure><ol><li>Both of these rank* functions work in the same manner as we define ranks in any exam.</li><li>There is a minor difference in DENSE_RANK() and RANK() functions.</li><li>Same as <a href="http://qsys400.com/db2-sql-olap-row_number/">ROW_NUMBER() </a>, OVER() function is required.</li><li><strong>But ORDER BY parameter is required in the OVER() function.</strong></li></ol><p>— Blank OVER() will not work</p><p>— If you use“PARTITION BY,” it must be followed by “ORDER BY.”</p><p>5. “ORDER BY” defines how to want to give the ranks.</p><h3>1. DENSE_RANK()</h3><ol><li>This works exactly like the exam ranking logic defined at the starting of this article.</li></ol><p>— Based on “ORDER BY,” the topmost row and all other matching rows get rank — 2nd and all matching rows get rank 2, and so on.</p><p>2. There will be no gaps in the rank sequence. This means no sequence number will be missing between the 1 and the highest rank sequence.</p><h3>OVER(ORDER BY…)</h3><pre>select a.*, DENSE_RANK() OVER(<strong>ORDER BY MARKS <em>DESC</em></strong>) as DENSE_RANK from RESULT a</pre><ol><li>Both rows with 900 marks are ranked 1.</li><li>Row with 800 marks is ranked 2.</li><li>All 3 rows with 600 marks are ranked 4.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*DWRK5UdenYiElljq8q4BAw.png" /></figure><h3>OVER(PARTITION BY… ORDER BY…)</h3><ol><li>“PARTITION BY” works the same as in ROW_NUMBER() function.</li></ol><p>— Create a virtual partition in rows, and each partition has its own set of sequence numbers starting with 1.</p><pre>select a.*, DENSE_RANK() OVER(<strong>PARTITION BY MARKS</strong>  ORDER BY NAME) as DENSE_RANK </pre><pre>from RESULT a</pre><ol><li>MARKS creates partitions, so each set of equal marks get its own set of rank sequence.</li><li>After that, ranks are assigned based on NAME (ORDER BY NAME).</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*FrKKlMRvpRyRV9oEVeWrlw.png" /></figure><h3>2. RANK()</h3><p>Here is how RANK() is different from DENSE_RANK().</p><ol><li>Suppose you ask all participants to make a queue by their marks only. (Highest mark in front and lowest in back).</li><li>The queue will look like some this.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*nYZogSndSy5yAy5Nhg4W-w.png" /></figure><p>Here is how RANK() works</p><ol><li>Same marks always get the same rank. So</li><li>Top 900 occupy positions 1 and 2. But you can not tell which one will go for position 1 and which one for position 2.</li></ol><p>— So both get RANK 1</p><ol><li>Both 900 got RANK 1, but they occupied the first 2 positions</li><li>So 800 will get the RANK 3. This will create a gap as there is no one with RANK 2.</li><li>700 will get the RANK 4.</li><li>Three 600 occupy positions 5,6 and 7; you can not tell which one gets which position.</li></ol><p>— So assign all three the same RANK 5.</p><ol><li>Now 500 will get RANK 8, creating gaps for RANK 6 and RANK 7.</li><li>and SO ON…</li></ol><p>This example with RANK() and DENSE_RANK() will help you understand how RANK() works in comparison to DENSE_RANK()</p><pre>select a.*, <br><em>RANK()</em> OVER(<strong>ORDER BY MARKS <em>DESC</em></strong>) as RANK, <br><em>DENSE_RANK()</em> OVER(<strong><em>ORDER BY MARKS DESC</em></strong>) as DENSE_RANK  <br>from RESULT a</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*gf77BBgHwKw7otYKUSfyKw.png" /><figcaption>No gaps</figcaption></figure><p><strong>RANK() OVER(PARTITION BY… ORDER BY…) work in the same concept as in DENSE_RANK() OVER(PARTITION BY… ORDER BY…) as above</strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1edc82053abe" width="1" height="1" alt=""><hr><p><a href="https://medium.com/applied-i/db2-sql-olap-part-3-rank-and-dense-rank-1edc82053abe">DB2 SQL OLAP PART 3: RANK and DENSE_RANK</a> was originally published in <a href="https://medium.com/applied-i">Applied I</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[DB2 SQL OLAP PART 2: ROW_NUMBER]]></title>
            <link>https://medium.com/applied-i/db2-sql-olap-part-2-row-number-c1cae076a49f?source=rss----1242cf7f716b---4</link>
            <guid isPermaLink="false">https://medium.com/p/c1cae076a49f</guid>
            <dc:creator><![CDATA[Sumit goyal]]></dc:creator>
            <pubDate>Wed, 26 May 2021 04:42:27 GMT</pubDate>
            <atom:updated>2021-05-24T19:59:14.188Z</atom:updated>
            <content:encoded><![CDATA[<ul><li>ROW_NUMBER is the most basic OLAP function.</li><li>It is straightforward, powerful, and convenient to use.</li><li>ROW_NUMBER assigns a temporary number to each row of the result set returned by SQL statement.</li></ul><p>The most basic usage of this function looks like following-</p><pre>SELECT a.* , ROW_NUMBER() OVER() FROM address a</pre><p>Each row selected from table ‘address’ is assigned a unique sequence number starting with ‘1’ and keeps increasing in the order rows are fetched by SQL statement.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ghuUX2g4_1KETBCm_jBpuA.png" /></figure><p>The above SQL statement is similar to the SQL statement below-</p><pre>SELECT  a.* , ROW_NUMBER() <br>over(order by ADDID, ADDRESS, CITY, STATE, ZIP, COUNTRY ) <br>FROM address a</pre><p>As stated earlier, the ROW_NUMBER function assigns the number in the order rows are fetched by SQL statement; so, if the fetch sequence of a row changes due to any factor, the assigned number also changes for that row. (Refer to an example below.)</p><pre>SELECT  a.* , ROW_NUMBER() over() <br>FROM address a <strong>ORDER BY a.CITY</strong></pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*3iXhU08uAh9m6ktMtGq9hw.png" /></figure><h3>OVER()</h3><p>It is important to know that ROW_NUMBER() function always needs a function OVER() to work. OVER() provides two options to define how ROW_NUMBER would assign the numbers to the rows in the result set. These options are-</p><ol><li>ORDER BY</li><li>PARTITION BY</li></ol><h3>OVER (ORDER BY … )</h3><ol><li>ORDER BY allows to define the ordering sequence in which the sequence number should be assigned to the rows fetched by SQL.</li><li>Always assigns a unique number to each row starting from 1.</li><li>This works in the same way as the ORDER BY clause works in a simple select statement.</li><li>ASC (Ascending) and DESC (Descending) options are allowed.</li></ol><pre>SELECT a.* , ROW_NUMBER() over(<strong>ORDER BY CITY DESC, ZIP</strong>) as ROW_NUMBER<br> FROM address a <em>order by CITY</em></pre><p><strong>NOTE</strong>: due to the <em>order by CITY </em>clause, the display sequence is different from the ROW_NUMBER sequence. ROW_ NUMBER is assigned for <strong><em>Descending</em></strong><em> </em>CITY column while records are being displayed in <strong><em>Ascending </em></strong>CITY column.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ZfDElgzLP_mkBKHwjgJPzA.png" /></figure><h3>OVER (PARTITION BY … )</h3><ol><li>PARTITION BY divide the data into virtual partitions and each partition gets its own set of rows (and hence ROW_NUMBER sequence).</li><li>Every set of ROW_NUMBER sequence starts with 1 (unique within a respective partition), so there may be duplicate ROW_NUMBER values in the result set.</li></ol><pre>SELECT a.* , ROW_NUMBER() OVER(<strong>PARTITION BY COUNTRY</strong>) as ROW_NUMBER<br> FROM address a</pre><p>NOTE: <strong>PARTITION BY COUNTRY </strong>creates 2 virtual partitions in data; one for COUNTRY = INDIA and the other for COUNTRY = USA. Each partition has its own set of <strong><em>ROW_NUMBERs </em></strong><em>starting with 1.</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*hF1NpixDHjXhIHjDliTVVA.png" /></figure><h3>OVER (PARTITION BY … ORDER BY… )</h3><ol><li>Within each virtual partition created by “PARTITION BY,” an “ORDER BY” clause can be used to define the order of sequence number generated by the ROW_NUMBER() function.</li><li>Please be sure that OVER(ORDER BY … PARTITION BY…) is <strong>NOT ALLOWED</strong>.</li></ol><pre>SELECT a.* , ROW_NUMBER() OVER(<strong><em>PARTITION BY COUNTRY</em></strong> <strong>ORDER BY ZIP DESC</strong>) as ROW_NUMBER<br> FROM address a</pre><p>Note: SQL statement first creates partitions by COUNTRY and then orders each partition by ZIP in descending order.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*PgrrqEK0UTkiRJT_YNGq3A.png" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c1cae076a49f" width="1" height="1" alt=""><hr><p><a href="https://medium.com/applied-i/db2-sql-olap-part-2-row-number-c1cae076a49f">DB2 SQL OLAP PART 2: ROW_NUMBER</a> was originally published in <a href="https://medium.com/applied-i">Applied I</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[DB2 SQL OLAP: Online Analytical Processing Part 1]]></title>
            <link>https://medium.com/applied-i/db2-sql-olap-online-analytical-processing-part-1-a30a1922e7fb?source=rss----1242cf7f716b---4</link>
            <guid isPermaLink="false">https://medium.com/p/a30a1922e7fb</guid>
            <category><![CDATA[ibm-i-series]]></category>
            <category><![CDATA[ibm-i]]></category>
            <category><![CDATA[olap]]></category>
            <category><![CDATA[sql]]></category>
            <category><![CDATA[db2]]></category>
            <dc:creator><![CDATA[Sumit goyal]]></dc:creator>
            <pubDate>Wed, 26 May 2021 04:42:19 GMT</pubDate>
            <atom:updated>2021-05-17T19:59:28.227Z</atom:updated>
            <content:encoded><![CDATA[<p>OLAP functions: <strong>O</strong>n<strong>L</strong>ine <strong>A</strong>nalytical <strong>P</strong>rocessing functions</p><p>What is online here?<br>An online algorithm can serially process its input piece-by-piece. So an online algorithm is one that never has access to all data at the same time. (So it’s streaming data)</p><p>Advantages-</p><ol><li>OLAP functions are beneficial to create complex reports using a single SQL statement.</li><li>OLAP functions provide multiple and very advanced data grouping and ordering options, which are not possible by simple “GROUP BY” and/or “ORDER BY” clauses.</li></ol><p>Below is the list of available OLAP functions.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*XTpVyo29BMxVwdZgSms4pg.png" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a30a1922e7fb" width="1" height="1" alt=""><hr><p><a href="https://medium.com/applied-i/db2-sql-olap-online-analytical-processing-part-1-a30a1922e7fb">DB2 SQL OLAP: Online Analytical Processing Part 1</a> was originally published in <a href="https://medium.com/applied-i">Applied I</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[ILE RPG: Named Indicators]]></title>
            <link>https://medium.com/applied-i/ile-rpg-named-indicators-790b73b65bd6?source=rss----1242cf7f716b---4</link>
            <guid isPermaLink="false">https://medium.com/p/790b73b65bd6</guid>
            <category><![CDATA[ibm-i]]></category>
            <category><![CDATA[ile-rpg]]></category>
            <category><![CDATA[ibm-iseries]]></category>
            <category><![CDATA[rpg]]></category>
            <category><![CDATA[rpgle]]></category>
            <dc:creator><![CDATA[Sumit goyal]]></dc:creator>
            <pubDate>Wed, 26 May 2021 04:41:24 GMT</pubDate>
            <atom:updated>2021-05-17T04:27:02.478Z</atom:updated>
            <content:encoded><![CDATA[<p>From ancient times we RPG programmers have been using INDICATORS from handling display files to tracking errors. But maintaining source with indicators in INXX(XX= 01 to 99) form is always complex. So, the concept of “Named Indicators” gives programmers the power to provide long readable names to Indicators that are easy to maintain.</p><p>Here how we can use Named Indicators in RPG:</p><h3>Using Pointer and DS.</h3><p>D pIndicators S * Inz(%Addr(*In))<br>D Indicators DS Based(pIndicators)<br>D ExitKey N Overlay(Indicators:3)<br>D PromptKey N Overlay(Indicators:4)<br>D RefershKey N Overlay(Indicators:5)<br>D ClearSubfile N Overlay(Indicators:41)<br>D DisplaySubfileControl...<br>D N Overlay(Indicators:42)</p><p>Now in your RPG code, you don’t need to use *IN03 = *ON; instead, you can use ExitKey = *On. For Example, in free format RPG, you can write code something like this :</p><pre>DoW ExitKey = *Off;<br>  DisplaySubfileControl = *Off;<br>  ClearSubfile = *On;<br>  Write SUBFILE_CONTROL_FORMAT;<br>  ClearSubfile = *Off ;<br>EndDo</pre><h3>Using INDDS.</h3><p>Wise words from IBM-</p><p>The INDDS keyword lets you associate a data structure name with the INDARA indicators for a workstation or printer file. This data structure contains the conditioning and response indicators passed to and from data management for the file and is called an indicator data structure.</p><p>In simple words-</p><ol><li>Your Display or Printer file must contain INDARA keyword at File-Level.</li></ol><p>Example how to use INDDS in RPG:</p><pre>FExample1  CF   E             WORKSTN INDDS(<strong><em>dispInds</em></strong>) <br><br> <br>D <strong><em>dispInds</em></strong>        DS                  <br>D  ExitKey                        N   Overlay(dispInds:3)<br>D  PromptKey                      N   Overlay(dispInds:4)<br>D  RefershKey                     N   Overlay(dispInds:5)<br>D  ClearSubfile                   N   Overlay(dispInds:41)<br>D  DisplaySubfileControl...<br>D                                 N   Overlay(dispInds:42)</pre><p>This method removes the connection between *INXX indicators and Display file(or printer file). If you need to track whether F3 key is pressed or not, you cannot use *In03. Instead, you have to use ExitKey = *ON.</p><p>INDDS will be different for each file. So if you are using multiple display files, you have to track F3 using their respective INDDS indicator names.</p><p><a href="https://www.ibm.com/support/knowledgecenter/en/ssw_ibm_i_72/rzasd/findds.htm">More Details on IBM Site</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=790b73b65bd6" width="1" height="1" alt=""><hr><p><a href="https://medium.com/applied-i/ile-rpg-named-indicators-790b73b65bd6">ILE RPG: Named Indicators</a> was originally published in <a href="https://medium.com/applied-i">Applied I</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[ILE RPG: Track ENTER key]]></title>
            <link>https://medium.com/applied-i/ile-rpg-track-enter-key-114a0028523?source=rss----1242cf7f716b---4</link>
            <guid isPermaLink="false">https://medium.com/p/114a0028523</guid>
            <category><![CDATA[rpgle]]></category>
            <category><![CDATA[rpg]]></category>
            <category><![CDATA[ibm-i]]></category>
            <category><![CDATA[ile-rpg]]></category>
            <category><![CDATA[ibm-iseries]]></category>
            <dc:creator><![CDATA[Sumit goyal]]></dc:creator>
            <pubDate>Wed, 26 May 2021 04:41:13 GMT</pubDate>
            <atom:updated>2021-05-17T04:26:49.639Z</atom:updated>
            <content:encoded><![CDATA[<p>In RPG, how can we track if the user pressed any of the function keys (F01 to F24) on the screen? Of course, by using CA/CF indicators. But how can we check if the user pressed the enter key on the screen?</p><p>To track enter key, we need to use a simple trick involving <a href="https://publib.boulder.ibm.com/iseries/v5r1/ic2924/books/c092508378.htm">File information data structure(INFDS) </a>and a hexadecimal value.</p><pre>FSFLXXXXXD CF   E             WORKSTN INFDS(FileInfo)<br><br> *---------------------------------------------------------------<br> *  File information Data structure<br> *---------------------------------------------------------------<br>D FileInfo        DS<br>D KeyPressed            369    369<br><br> *---------------------------------------------------------------<br> *  Constant<br> *---------------------------------------------------------------<br>D EnterKey        C                   CONST(x&#39;F1&#39;)</pre><p>1. We declared a display file SFLXXXXXD with INFDS points to the FileInfo data structure.</p><p>2. AS400 updates Position from 369 to 369 in INFDS with Hexadecimal value corresponding to the key pressed on the screen.</p><p>3. We declared a constant “EnterKey” with hexadecimal value x’F1′.( x for hexadecimal).</p><p>So every time user presses Enter key on the screen. AS400 system updates variable KeyPressed (in FileInfo DS) with a hexadecimal value of x’F1′. Now, we can compare EnterKey constant with Keypressed variable :</p><pre>Select ;<br>    When KeyPressed = EnterKey;<br>         ExSr ValidateData;<br>EndSl;</pre><p>Using this way, you can track almost all keys, including function keys. Here is a list of Hexadecimal values for different keys.</p><pre>D F1              C                   CONST(X&#39;31&#39;)<br>     D F2              C                   CONST(X&#39;32&#39;)<br>     D F3              C                   CONST(X&#39;33&#39;)<br>     D F4              C                   CONST(X&#39;34&#39;)<br>     D F5              C                   CONST(X&#39;35&#39;)<br>     D F6              C                   CONST(X&#39;36&#39;)<br>     D F7              C                   CONST(X&#39;37&#39;)<br>     D F8              C                   CONST(X&#39;38&#39;)<br>     D F9              C                   CONST(X&#39;39&#39;)<br>     D F10             C                   CONST(X&#39;3A&#39;)<br>     D F11             C                   CONST(X&#39;3B&#39;)<br>     D F12             C                   CONST(X&#39;3C&#39;)<br>     D F13             C                   CONST(X&#39;B1&#39;)<br>     D F14             C                   CONST(X&#39;B2&#39;)<br>     D F15             C                   CONST(X&#39;B3&#39;)<br>     D F16             C                   CONST(X&#39;B4&#39;)<br>     D F17             C                   CONST(X&#39;B5&#39;)<br>     D F18             C                   CONST(X&#39;B6&#39;)<br>     D F19             C                   CONST(X&#39;B7&#39;)<br>     D F20             C                   CONST(X&#39;B8&#39;)<br>     D F21             C                   CONST(X&#39;B9&#39;)<br>     D F22             C                   CONST(X&#39;BA&#39;)<br>     D F23             C                   CONST(X&#39;BB&#39;)<br>     D F24             C                   CONST(X&#39;BC&#39;)<br>      * Page Down/Roll Up                              <br>     D RollUp          C                   CONST(X&#39;F5&#39;)<br>     D PageDown        C                   CONST(X&#39;F5&#39;)<br>      * Page Up/Roll Down                              <br>     D RollDown        C                   CONST(X&#39;F4&#39;)<br>     D PageUp          C                   CONST(X&#39;F4&#39;)<br>      * Enter                                          <br>     D Enter           C                   CONST(X&#39;F1&#39;)<br>     D Help            C                   CONST(X&#39;F3&#39;)<br>     D Print           C                   CONST(X&#39;F6&#39;)</pre><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=114a0028523" width="1" height="1" alt=""><hr><p><a href="https://medium.com/applied-i/ile-rpg-track-enter-key-114a0028523">ILE RPG: Track ENTER key</a> was originally published in <a href="https://medium.com/applied-i">Applied I</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[DB2 for I: Index internals. Part-3 Encoded Vector Index]]></title>
            <link>https://medium.com/applied-i/db2-for-i-index-internals-part-3-encoded-vector-index-ce691f68bd36?source=rss----1242cf7f716b---4</link>
            <guid isPermaLink="false">https://medium.com/p/ce691f68bd36</guid>
            <category><![CDATA[index]]></category>
            <category><![CDATA[ibm-i]]></category>
            <category><![CDATA[db2]]></category>
            <category><![CDATA[sql]]></category>
            <category><![CDATA[ibm-iseries]]></category>
            <dc:creator><![CDATA[Sumit goyal]]></dc:creator>
            <pubDate>Wed, 26 May 2021 04:40:30 GMT</pubDate>
            <atom:updated>2021-05-15T23:29:21.897Z</atom:updated>
            <content:encoded><![CDATA[<h3>Encoded Vector Index or EVI</h3><ol><li>It’s IBM’s version of the Bitmap index.</li><li>EVI is relatively new compared to Radix Index.</li><li>Logical files do not support EVI.</li><li>Use “CREATE<strong> ENCODED VECTOR</strong> INDEX ….” Statement to create EVI index on the table</li><li>It’s very efficient for:</li></ol><ul><li>Small set or say defined set of distinct keys like States in the USA.</li><li>Read-only table</li></ul><h3>A quick look into Bitmap Index</h3><p>Let say this table represents the keys and corresponding RRNs.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*s2DTBX-bAmbLoybJIbXcvg.png" /></figure><p>Here is the Bitmap index for these keys(with RRN)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*uvD-8-VAd8vmG3Ayf8p_lw.png" /></figure><ol><li>Bitmap Index is suitable for small values.</li><li>As the number of keys increase (new RRNs) number of bits needs to store the index also increased. (Issue 1)</li><li>The System has to update the complete index every time a new key comes in. (Issue 2)</li></ol><p>So, IBM created a modified version called Encoded Vector Index, aka EVI.</p><h3>EVI: Encoded Vector Index</h3><p>EVI has two parts</p><ol><li>Symbol table:</li></ol><ul><li>It contains a distinct list of keys.</li><li>A reference (called code) to an element in the Vector list.</li><li>And it may contain the values for some SQL functions like sum(), count(),avg().</li></ul><p>2. Vector list:</p><ul><li>It’s just a list.</li><li>Each position represents the RRN from the base table.</li><li>This position is the only link between the index and the base table.</li><li>The value at a position is the link between the Symbol table and this list.</li></ul><p>Let say this is the data in the base table.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Qw-CvHk3izlfecbxsuF5ng.png" /></figure><p>The Symbol table might look like this.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8kIQSLMGge6zZf3-h13HPQ.png" /></figure><h3>Vector List :</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zHGVtij57H-ZHqYBHK-VOg.png" /></figure><p>So, let say the System needs to find a match for the key-value “TX.”</p><ol><li>Look into the Symbol table for the code for this key-value TX = 99</li><li>Now check the vector list for all the values equals 99.</li><li>RRN 1 and 4 in the base table contains the record for the key “TX.”</li></ol><p>If you add a new Key in the symbol table, it will only impact a single entry in the vector list. So unlike the Bitmap Index system don’t need to update the complete index. The System will create a new entry in the vector list.</p><h3>Memory allocation for the CODE (the reference between the Symbol table and the Vector list)</h3><ol><li>By default, DB2 allocates 1 byte for the code.</li></ol><ul><li>This means a total of 256 distinct keys (28) can be added to the symbol table.</li><li>If the number of distinct keys increased beyond 256</li></ul><p>— DB2 will allocate 2 bytes (then 4 bytes .. 8 bytes, and so on) for the code</p><p>— And rebuild the index.</p><ul><li>So, every time the size increases, the System has to rebuild the complete index.</li></ul><p>2. To limit these rebuilds, you can give some idea of how many distinct keys you expect in this index.</p><ul><li>So, based on this idea, the System will allocate an appropriate number of bytes for the code.</li></ul><blockquote><strong><em>CREATE ENCODED VECTOR INDEX XYZ on ABC(state)</em></strong></blockquote><blockquote><strong><em>WITH 3650 DISTINCT VALUES</em></strong></blockquote><ol><li>From this statement, System gets the idea that there might be 3650 distinct keys in this index.</li></ol><ul><li>So, 1-byte won’t be enough for 3650 values</li><li>But 2 bytes will be enough for now.</li></ul><p>2. This is not a hard limit. If the number of distinct keys in the index goes beyond 2 bytes, the System will allocate extra space and rebuild the index.</p><p>More references</p><ol><li><a href="https://www.ibm.com/developerworks/ibmi/library/i-evi-only-access-in-ibm-db2-for-i/index.html">https://www.ibm.com/developerworks/ibmi/library/i-evi-only-access-in-ibm-db2-for-i/index.html</a></li><li><a href="https://www.ibm.com/support/knowledgecenter/en/ssw_ibm_i_73/rzajq/howeviworks.htm">https://www.ibm.com/support/knowledgecenter/en/ssw_ibm_i_73/rzajq/howeviworks.htm</a></li></ol><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ce691f68bd36" width="1" height="1" alt=""><hr><p><a href="https://medium.com/applied-i/db2-for-i-index-internals-part-3-encoded-vector-index-ce691f68bd36">DB2 for I: Index internals. Part-3 Encoded Vector Index</a> was originally published in <a href="https://medium.com/applied-i">Applied I</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>