• The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
Menu
  • The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
  • Let One Row Represent A Group, Take Three

    October 27, 2015 Ted Holt

    Faithful reader Bill Cisne sent me an email with an SQL SELECT query. No comment, no explanation, just code. Bill had figured out how to use a lateral join to solve a problem and was kind enough to share his success with me. I have been aware of lateral joins for some time, but have not found a need for them in my work. Today I revisit a problem to illustrate one way that lateral joins can be useful.

    LATERAL is a type of for-each loop within a query. For each row that a SELECT statement (the “outer” query) returns, the system executes a second (or inner) query. The power of LATERAL is that the inner query may refer to columns from the outer query. Michael Sansoterra mentioned LATERAL a long while back in this august publication.

    To illustrate the workings of LATERAL, let’s return to an example I’ve used before: retrieving only one row per group. Let’s list an unshipped sales order with information from only one line item–the one with the earliest entry time.

    Here’s the raw detail data:

    Order  Line   Qty  Shipped Balance  Price  Time
      101    1     10       10       0   4.00  2015-10-21-08.14.06
      101    2     12        0      12   1.00  2015-10-21-11.15.32
      101    3      8        0       8   3.00  2015-10-28-14.14.37
      102    1     10        5       5   2.00  2015-10-21-10.05.12
      103    3      5        0       5   1.10  2015-10-21-14.37.25
      104    1      5        5       0   3.50  2015-10-21-14.58.21
      105    1      4        4       0   5.00  2015-10-21-15.30.44
      105    2      6        0       6   2.00  2015-10-21-15.30.45
    

    Notice that there are two incomplete lines for order 101.

    Here’s the query:

    select h.OrderNo,
          substr(char(h.OrderDate),1,10) as OrderDate,
          d.LineNo,
          (d.QtyOrdered - d.QtyShipped) as Balance,
          d.Price,
          dec((d.QtyOrdered - d.QtyShipped) * d.Price,7,2)
                as Extended,
          substr(char(d.crttime), 1, 16) as TimeEntered
     from SalesOrdH as h,
     lateral (select *
                from SalesOrdD as x
               where h.orderno = x.orderno
                 and x.QtyShipped < x.QtyOrdered
               order by x.crttime
               fetch first row only) as d
    

    To deepen my understanding, I’ve been working through the examples in Michael R. Jones’ fabulous ebook, Converting RPG to Set Based SQL (Part 1: Input Operations). Michael uses a slightly different syntax, which works just as well as the previous example.

    select h.OrderNo,
           h.CustNo,
           substr(char(h.OrderDate),1,10) as OrderDate,
           d.LineNo,
           (d.QtyOrdered - d.QtyShipped) as Balance,
           d.Price,
           dec((d.QtyOrdered - d.QtyShipped) * d.Price,7,2)
                 as Extended,
           substr(char(d.crttime), 1, 16) as TimeEntered
      from SalesOrdH as h
     cross join lateral (select *
                           from SalesOrdD as x
                          where h.orderno = x.orderno
                            and x.QtyShipped < x.QtyOrdered
                       order by x.crttime
                          fetch first row only) as d
    

    Both queries return the same report:

    Order  Customer  Order date Line   Balance  Price  Extended Time
      101  80112300  2015-10-20   2         12   1.00     12.00 2015-10-21-11.15
      102  25000300  2015-10-20   1          5   2.00     10.00 2015-10-21-10.05
      103  65888800  2015-10-21   3          5   1.10      5.50 2015-10-21-14.37
      105  42221700  2015-10-21   2          6   2.00     12.00 2015-10-21-15.30
    

    To understand this, let’s begin with the outer query. It selects a few columns from the order header table and a few columns (some of which are calculated) from a lateral expression, i.e. an inner query. For each sales order header row, the query engine runs the inner query to retrieve one row from the sales order detail table. This inner query looks for the earliest-dated detail row which has not been completely shipped.

    Notice that the nested query refers to a table in the outer query (correlation name h). That’s that power of LATERAL that I mentioned above.

    LATERAL was added to DB2 some 11 years ago. Don’t you agree that it’s about time I got around to mastering it?

    RELATED STORIES

    For i Scalar Function Performance Considerations

    Let One Row Represent a Group, Take 2

    Let One Row Represent a Group

    More V5R3 SQL Enhancements

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    Tags:

    Sponsored by
    FalconStor

    Begin Your Journey to the Cloud with Hybrid Cloud Date Protection and Disaster Recovery

    FalconStor StorSafe optimizes and modernizes your IBM i on-premises and in the IBM Power Virtual Server Cloud

    FalconStor powers secure and encrypted IBM i backups on-premise and now, working with IBM, powers migration to the IBM PowerVS cloud and on-going backup to IBM cloud object storage.

    Now you can use the IBM PowerVS Cloud as your secure offsite copy and take advantage of a hybrid cloud architecture or you can migrate workloads – test & development or even production apps – to the Power VS Cloud with secure cloud-native backup, powered by FalconStor and proven IBM partners.

    Learn More

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    Sponsored Links

    Connectria:  Need help managing your IBM i? Trust us as an extension of your IT department.
    HelpSystems:  How do you use IBM i? Your peers want to know! Take the survey >
    Rocket Software:  Mobile app development and deployment solution for IBM i. Download FREE trial!

    Academic Initiative Lives Up To Its Name How To Join The Power Linux Evolution

    Leave a Reply Cancel reply

Volume 15, Number 22 -- October 27, 2015
THIS ISSUE SPONSORED BY:

ProData Computer Services
WorksRight Software
United Computer Group, Inc.

Table of Contents

  • Using Adopted Authority Wisely
  • Let One Row Represent A Group, Take Three
  • Questions About AES Encryption In RPG, DB2 for i, And The Web

Content archive

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

Recent Posts

  • To Comfort The Afflicted And Afflict The Comfortable
  • How FalconStor Is Reinventing Itself, And Why IBM Noticed
  • Guru: When Procedure Driven RPG Really Works
  • Vendors Fill In The Gaps With IBM’s New MFA Solution
  • IBM i PTF Guide, Volume 27, Number 27
  • With Power11, Power Systems “Go To Eleven”
  • With Subscription Price, IBM i P20 And P30 Tiers Get Bigger Bundles
  • Izzi Buys CNX, Eyes Valence Port To System Z
  • IBM i Shops “Attacking” Security Concerns, Study Shows
  • IBM i PTF Guide, Volume 27, Number 26

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