====================================================================== USE SQL IN REPORT LOOKUPS TO PUT SUMS & OTHER STATS IN THE HEADER ====================================================================== PRODUCT : R:BASE VERSION : 3.1B or Higher CATEGORY : REPORTS SUBCATEGORY : SQL, EXPRESSIONS ====================================================================== Advanced Reporting Technique R:BASE 3.1 or higher & Personal R:BASE 1.0 or higher You can use Structured Query Language (SQL) in a simple report lookup expression to look up sums, minimums, maximums, averages, and counts without programming. You can even look up these statistics in tables other than the report's base table. Use this powerful feature to accomplish tasks like these: <> Print a sum, a minimum, a maximum, an average, or a count in a report header or break header <> List a group total and the percent of grand total that the group total represents on each detail line of a report <> Print a report based on one primary table like CUSTOMER where each customer identification number (custid) is unique and in the process look up totals, averages, minimums, maximums, and counts using many rows in other transaction tables like transmaster, where several rows might contain the same custid number. SQL & Reports ============= This is possible because of the way R:BASE processes a report. As documented in R:BASE Reports Q & A in the November/December 1991 R:BASE EXCHANGE, R:BASE uses the report definition stored in the SYSREP table to build an SQL query when you print a report. Because it builds a SQL query, you can use the SQL SELECT functions in report lookup expressions. Basically, you can look up an expression or a SELECT function result because those are legal SQL operations. By using this technique, you can show totals, percentages, averages, minimums, maximums, and counts anywhere in a report even in the header or on every detail line. Although an R:BASE report goes row by row through the driving table and has no knowledge of groups of rows, SQL in a lookup expression can compute statistics that are based on groups of rows. Restrictions ============ This technique does have some limitations: <> The lookup expression or SQL function (the item you're looking up) must fit within a maximum length of 18 characters. <> The lookup must contain a WHERE clause. <> You cannot look up values in a view, only in a table. <> There's a limit to the number of lookup expressions you can have in a report (usually 30 to 40) before you run out of memory handles. For more information on this limit, see the last question and answer in R:BASE Reports Q & A in the November/December 1991 R:BASE EXCHANGE. If you have many other lookup expressions, you might not be able to take advantage of this technique. You can use any legal SQL function or expression in a report lookup as long as the entire item including the required opening and closing parentheses, the internal parentheses, and the function name (SUM, MIN, MAX, AVG, or COUNT) is 18 or fewer characters in length. If your column names are longer than eight characters, abbreviate them in the SQL functions by using the first eight characters. Looking Up Expressions ====================== If you're using an expression instead of an SQL function, conserve on space by omitting all spaces. Looking up an expression is handy when, for example, you want the complete name when the first name is in FNAME and the last name is in LNAME. Use the following lookup expression to look up the complete name in one pass: vname (fname&lname) IN customer WHERE custid = custid It works because (FNAME+LNAME) is only 13 characters. If both the column names had eight characters, the lookup item would be over the 18-character limit, thus the expression wouldn't work. You can use the same technique to grab the state and ZIP code in one pass: vsz = (state&zipcode) IN customer WHERE custid = custid Pound-position Abbreviations ============================ If you have long column names, you can still use this technique by using the pound-position shorthand for columns. But it can lead to problems later on if you change the order of the columns in the table. The pound- position shorthand is the pound sign (#) in combination with the column's position number in the table list. For example, custid is the second column in the transmaster list, so you could use #2 in place of custid. Use the LIST command to list the customer table (in Personal R:BASE, press [F3] and choose customer under Columns to view the list of columns in customer). You'll see that city is the fourth column, state is the fifth, and zipcode is the sixth. Therefore, you could look up all three columns at once by using this lookup expression: vcsz = (#4+',') IN customer WHERE custid = custid By using the abbreviation, you can look up a lot of columns at once, but the pound-position abbreviations will cause you headaches later on if you change the physical order of the columns in the table. You could change the order by using the PROJECT command, for example, or by removing a column and adding it back in. Only in Reports =============== R:BASE doesn't process form lookups by using SQL queries, so you can use this technique only in reports lookups and not in forms lookups. Putting the Balance in a Header =============================== Below are several examples that demonstrate how easy use SQL lookups can be. Look at Printing a Bill in the November/December 1991 R:BASE EXCHANGE. The third and fourth expressions use the SUM function to add up all the charges and payments so that the customer's balance can be computed and printed at the top of the bill. Here are those expressions: vchgsum = (SUM(amount)) IN charges WHERE custid = custid vpaysum = (SUM(amount)) IN payments WHERE custid = custid The fifth expression computes the balance: vbal = (.vchgsum .vpaysum) The report is based on a view that combines three tables (customer, payments, and charges). The sums and the balance are computed for every row in the view, so you can print any of these amounts at any time in a header, in the detail lines, or in a footer. You don't have to wait for R:BASE to go through all the rows. Summary Statistics in Customer Report ===================================== Here's another example. This is a modification of the customer report in the concomp sample database included with R:BASE 3.1. The report is based on the customer table, which lies on the one- side of two one-to- many relationships with other tables. The many-side tables directly related to customer are contact and transmaster. Add the following lookup expressions to look up how many times a customer has been contacted, the customer's total order amount, largest order, smallest order, the average of all the customer's orders, and the percentage of total revenue that customer's total represents: vtalked = (COUNT(custid)) IN contact WHERE custid = custid vtotord = (SUM(netamount)) IN transmaster WHERE custid = custid vmaxord = (MAX(netamount)) IN transmaster WHERE custid = custid vminord = (MIN(netamount)) IN transmaster WHERE custid = custid vavgord = (AVG(netamount)) IN transmaster WHERE custid = custid vgrand = (SUM(netamount)) IN transmaster WHERE custid IS NOT NULL vpercent = ((.vtotord / .vgrand) * 100) These variables are computed for every row in customer, which is the driving table for the report. Because customer is the one-side table, no breakpoints are necessary (each custid appears in only one row). You can locate the summary variables in the detail section and they'll print for each customer. For example, you might want to add this these extra detail lines to the detail section of the customer report: Times Contacted: S vtalked E Total Orders: S vtotord E Percent of All Orders: S vpercent E percent Largest Single Order: S vmaxord E Smallest Single Order: S vminord E Average Order: S vavgord E You can use this technique any time you want to base a report on a one-side (master or header) table and print summary statistics on amounts stored in the many-side (transaction) tables. Adding a Picture Format ======================= You'll probably want to put a label such as Percent of All Orders: in front of summary items, as in the example above. When you use a label, you might want to left justify the item by adding a picture format to the field. Remember, when you add [<] to the picture format to left justify a numeric field like CURRENCY, you must also include characters modifiers. If you don't, the amounts won't print; you'll get asterisks (*). Here's an example of a picture format for a CURRENCY variable that you want to left justify and that will never be larger than 99 million dollars: [<]$99,999,999.00 You might get customers listed in the report who haven't ordered anything yet, so add the following as the NULL picture format: No Orders Yet ============= Now the report will automatically print No Orders Yet next to the appropriate label. Other Opportunities =================== Use this technique in any report in which you want to look up and print summary information (sums, averages, minimums, maximums, and counts). You can even use it to look up and summarize values in the driving table.