• The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
Menu
  • The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
  • Conditional SQL I/O, Take 2

    March 20, 2017 Ted Holt

    Bob writes, “Hey, Ted! I hope you can teach an old dog a new trick. I am trying to replace the CHAIN operation with SQL. I chain once to a file to read a certain record. If that record is not found, I chain again to retrieve a default record. How can I make SQL do a second read to the same file?”

    This is not a hard thing to do, as SQL has no problem joining more than once to the same table. I’ll show you two methods to retrieve your data. The first method is the easier one, but you can only use it if the table cannot store null values in the columns (fields) that you’re retrieving. (Such is the case in many IBM i shops.) The second method works whether or not the columns can contain null values.

    Let’s set up the situation by defining two physical files – a customer master file (CUSTMAST) and a customer addresses file (CUSTADDR). The former has one record per customer.

    A                                      UNIQUE
    A          R MASTREC
    A            ID             3  0
    A            NAME          24
    A          K ID

    The customer address file may have one or two rows per customer, each distinguished by the address type code.

    A                                      UNIQUE
    A          R ADDRREC
    A            ID             3  0
    A            TYPE           1
    A            ADDRESS1      16
    A            ADDRESS2      16
    A            CITY          16
    A            STATE          2
    A            ZIPCODE       10
    A          K ID
    A          K TYPE

    The address type has the value 1 for a billing address and 2 for a shipping address. To keep this example as simple as possible, assume that all customers have a billing address, but only some customers have a shipping address. If a customer has no shipping address, we ship to the billing address.

    Let’s read the customer master and list the shipping addresses. To simplify the example even more, I omit the city, state, and ZIP (postal) code. (They would be handled in the same way the two address line columns are handled.)

    Here’s the customer address data:

    Here’s some RPG code that is typical of many shops:

    FCustMast  if   e           k disk
    FCustAddr  if   e           k disk
    Fqsysprt   o    f  132        printer
    
    C     AddrKey       klist
    C                   kfld                    ID
    C                   kfld                    AddrType          1
    C
    C                   read      MastRec                                90
    C                   dow       *in90 = *off
    C                   eval      AddrType = '2'
    C     AddrKey       chain     AddrRec                            91
    C                   if        *in91 = *on
    C                   eval      AddrType = '1'
    C     AddrKey       chain     AddrRec                            91
    C                   endif
    C                   if        *in91 = *on
    C                   clear                   Address1
    C                   clear                   Address2
    C                   endif
    C                   except    pline
    C                   read      MastRec                                90
    C                   enddo
    C
    C                   eval      *inlr = *on
    
    Oqsysprt   e            pline
    O                       ID
    O                       Name             +   1
    O                       Address1         +   1
    O                       Address2         +   1

    Notice the two CHAIN operations to CUSTADDR. If the first CHAIN does not find the shipping address, the program chains again to retrieve the billing address. Now, how do we do the same sort of thing using SQL?

    Method 1

    The first method only works if the columns cannot contain null values. Here’s the query:

    select m.ID, m.Name,
           coalesce (s.Address1, b.Address1) as Address1,
           coalesce (s.Address2, b.Address2) as Address2
      from CustMast as m
      left join CustAddr as s
        on (m.ID = s.ID and s.type = '2')
      left join CustAddr as b
        on (m.ID = b.ID and b.type = '1')

    Notice that the customer address table is joined twice. The first join retrieves the shipping address (type 2). The second join retrieves the billing address (type 1). If the shipping address does not exist, the columns from the type 2 row will be null.

    Notice also the COALESCE functions. COALESCE selects the first non-null value from a list. Since the Address1 and Address2 columns cannot store null values, the query selects the billing address if the shipping address is not in the table.

    As I said, this query will not work if null values are permitted in the address fields. Here’s what the query would return if null were allowed and used in address line columns:

    Notice Dostoyevsky. His first address line comes from the shipping record, but the second address line comes from the billing record. We need a way to determine whether the shipping address exists. That turns out to be very easy to do.

    Method 2

    Here are the same customer master and customer address tables defined the modern way.

    create table CustMast 
       ( ID   dec(3)   not null,
         Name varchar(24),             
       primary key (ID))
    
    create table CustAddr  
       ( ID         dec (3)       not null,
         Type       char(1)       not null,
         Address1   varchar(16),           
         Address2   varchar(16),           
         City       varchar(16),
         State      char(2),    
         ZipCode    char(10),   
       primary key (ID, Type))

    The key columns cannot have a null value, but the other columns may. Here’s the same customer address data, but this time with nulls:

    Here’s the query:

    select m.ID, m.Name,
           case when s.ID is not null
                   then s.Address1
                   else b.Address1 end as Address1,
           case when s.ID is not null
                   then s.Address2
                   else b.Address2 end as Address2
      from CustMast as m
      left join CustAddr as s
        on (m.ID = s.ID and s.type = '2')
      left join CustAddr as b
        on (m.ID = b.ID and b.type = '1')

    Instead of COALESCE functions, I use CASE expressions, but notice what the CASE expressions test. To make this work, you must test one of the columns of the primary key from the row that may or may not exist. I chose to test the ID column from the shipping address (s.ID). This test tells me whether the shipping address exists because the only way a column of a primary key can be null is when the join does not find a match.

    Here are the results.

    Notice that Dostoyevsky’s address came out right this time.

    This scenario is similar to a one I wrote about a few years ago, but in that tip, the second join was to a different file and I didn’t consider null values.

    RELATED STORY

    Conditional SQL I/O

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    Tags: Tags: Guru, IBM i, SQL

    Sponsored by
    WorksRight Software

    Do you need area code information?
    Do you need ZIP Code information?
    Do you need ZIP+4 information?
    Do you need city name information?
    Do you need county information?
    Do you need a nearest dealer locator system?

    We can HELP! We have affordable AS/400 software and data to do all of the above. Whether you need a simple city name retrieval system or a sophisticated CASS postal coding system, we have it for you!

    The ZIP/CITY system is based on 5-digit ZIP Codes. You can retrieve city names, state names, county names, area codes, time zones, latitude, longitude, and more just by knowing the ZIP Code. We supply information on all the latest area code changes. A nearest dealer locator function is also included. ZIP/CITY includes software, data, monthly updates, and unlimited support. The cost is $495 per year.

    PER/ZIP4 is a sophisticated CASS certified postal coding system for assigning ZIP Codes, ZIP+4, carrier route, and delivery point codes. PER/ZIP4 also provides county names and FIPS codes. PER/ZIP4 can be used interactively, in batch, and with callable programs. PER/ZIP4 includes software, data, monthly updates, and unlimited support. The cost is $3,900 for the first year, and $1,950 for renewal.

    Just call us and we’ll arrange for 30 days FREE use of either ZIP/CITY or PER/ZIP4.

    WorksRight Software, Inc.
    Phone: 601-856-8337
    Fax: 601-856-9432
    Email: software@worksright.com
    Website: www.worksright.com

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    One On One With HelpSystems’ Debbie Saugen IBM i Has A Cup Of Coffee With Watson

    2 thoughts on “Conditional SQL I/O, Take 2”

    • Rusty Gadberry says:
      March 20, 2017 at 1:17 pm

      Ted, doing it this way you don’t have to be concerned about nulls.

      select m.ID, m.Name, a.address1, a.address2
      from CustMast as m
      left join table( select address1, address2
      from CustAddr a
      where a.ID = m.ID
      and a.type in (‘1’, ‘2’)
      order by a.ID, a.type desc
      fetch first 1 rows only
      ) as a on 1=1
      where m.ID = someID

      Reply
    • Ted Holt says:
      March 29, 2017 at 10:31 am

      That’s a good idea too, Rusty, although things like “on 1=1” always look strange to me.

      Reply

    Leave a Reply Cancel reply

TFH Volume: 27 Issue: 18

This Issue Sponsored By

  • BCD Software
  • Profound Logic Software
  • COMMON
  • Linoma Software
  • Northeast User Groups Conference

Table of Contents

  • The Lowdown On Pricing For The Power S812 Mini
  • IBM i Has A Cup Of Coffee With Watson
  • Conditional SQL I/O, Take 2
  • One On One With HelpSystems’ Debbie Saugen
  • The Dark Side Of Automated Systems Is Bright

Content archive

  • The Four Hundred
  • Four Hundred Stuff
  • Four Hundred Guru

Recent Posts

  • Spring IBM i Tech Refreshes Will Come A Bit Later This Year
  • You Are Much More Than Power Systems, And So Are We
  • Startup Seeks The “Golden Path” for IBM i Modernization
  • What Can IBM Do To Make The Future Power S1112 Mini System Compelling?
  • IBM i PTF Guide, Volume 28, Number 15
  • Bob 1.0 Users Bugged By Lack Of One Feature
  • Here Come The AI-Based Code Modernization Offerings
  • Guru: Cohesion First – What A Procedure Should Be Responsible For
  • IBM Offers Trade-Ins On Storage To Grease The Upgrade Skids
  • IBM i PTF Guide, Volume 28, Number 14

Subscribe

To get news from IT Jungle sent to your inbox every week, subscribe to our newsletter.

Pages

  • About Us
  • Contact
  • Contributors
  • Four Hundred Monitor
  • IBM i PTF Guide
  • Media Kit
  • Subscribe

Search

Copyright © 2025 IT Jungle