• jessica.green2312 (11/15/2013)


    Hi everyone,

    I'm not even sure how to word this succinctly enough to search for this topic, so I apologize in advance if this is covered elsewhere! It almost feels like a gaps and islands issue, but not quite....

    Background Info:

    I am developing a form for a mortgage company. There can be any number of borrowers on a given loan, and the business has asked that this form return only 2 borrowers at a time for a loan. For example, if there are 3 borrowers for a loan, they want the first copy of the form to print the first 2 borrowers and then another copy of the form to print the 3rd. No matter how many copies are printed, they want the borrower information to be labeled as 'Borrower1' xyz and 'Borrower2' xyz. Also, there will be a LOT more fields returned on the real form, so the sample information below is very simplified test data.

    Sample Data:

    CREATE TABLE #t (LoanID VARCHAR(5), BorrowerName VARCHAR(20), BorrowerOrder INT);

    GO

    INSERT INTO #t VALUES

    ('::E', 'John Smith', 0)

    , ('::E', 'Jane Smith', 1)

    , ('::E', 'Rob Jackson', 2)

    , ('AF_CF', 'Sloan Burton', 1)

    , ('AF_CF', 'Virginia Burton', 2)

    , ('AF_CF', 'John Hardeman', 0)

    , ('::E', 'Mary Lamb', 4)

    , ('::E', 'Patrick Stewart', 3)

    So for loan 'AF_CF', the form should print twice:

    1st copy: Borrower1 = Sloan Burton, Borrower2 = Virginia Burton

    2nd copy: Borrower1 = John Hardeman, Borrower2 = NULL

    We are on 2012, so I tried to do this with LEAD():

    SELECT

    Borrower1 = BorrowerName

    , Borrower2 = LEAD(BorrowerName) OVER(ORDER BY BorrowerOrder)

    FROM

    #t AS t

    WHERE

    FileID = 'AF_CF'

    But this returns a record for every borrower, so the form is printing 3 times:

    1st: Borrower1 = Sloan Burton, Borrower2 = Virginia Burton

    2nd: Borrower1 = Virginia Burton, Borrower2 = John Hardeman

    3rd: Borrower1 = John Hardeman, Borrower2 = NULL

    I don't want that 2nd record to return. This result is what makes me think of gaps and islands, but I don't know if the 2nd record is really an island since it's (1) not stored this way...it's returning this way because of the query and (2) it's not sequential data....

    Finally, I tried restricting this by putting this into a CTE and then returning only the odd numbered records like I have below. This runs pretty quickly when dealing with one loan. But...I am concerned that the CTE will be slow when we run batches of loans.

    Attempt with CTE:

    --With CTE

    ;WITH cte AS

    (SELECT

    Borrower1 = BorrowerName

    , Borrower2 = LEAD(BorrowerName) OVER(ORDER BY BorrowerOrder)

    , RowNumber = ROW_NUMBER() OVER(ORDER BY BorrowerOrder)

    FROM

    #t AS t

    WHERE

    FileID = '::E'

    )

    SELECT

    *

    FROM

    cte

    WHERE

    RowNumber % 2 = 1

    Is there a better, cleaner way to do this? Or is the CTE the best way to go?

    This is actually pretty easy to do but I need some clarification on the Borrower Order column. 0 typically comes before 1 or 2 in the world of numbers. Why, in you example, do the BorrowOrder of 1 and 2 come before 0?

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)