Expand multi-join with another table

  • Hi all,
    I'm have a SQL agent job (running in live business situation) and it's doing the following:
    -read data from source DB (and some additional lookup) and keep it in a view  (see code)

    This has all been working perfectly for years and here the code:

    Code :   (view)

    ALTER VIEW [dbo].[StagingForCardManagement] AS
        select SFCM.*,dbo.CostPL.Description,dbo.CostPL.Template
        FROM(
        SELECT
      3 as Actie,
      CAST(t1.pers_nr as VARCHAR(32)) + CAST(t2.dv_vlgnr as VARCHAR(32)) COLLATE Latin1_General_CI_AS as persoonsnummer,
      CAST(t1.e_roepnaam as VARCHAR(40)) COLLATE Latin1_General_CI_AS as roepnaam,
      CAST(
                CASE WHEN t1.vrvg_samen is not null THEN t1.vrvg_samen + ' ' +
                    (
                    CASE WHEN (CHARINDEX('-', t1.naam_samen) > 0 ) THEN LEFT(naam_samen, CHARINDEX('-', naam_samen) - 1)
                    ELSE t1.naam_samen END)
                 ELSE
                    (
                    CASE WHEN (CHARINDEX('-', t1.naam_samen) > 0 ) THEN LEFT(naam_samen, CHARINDEX('-', naam_samen) - 1)
                  ELSE t1.naam_samen END
                  )
                 END
                 as VARCHAR(40)) COLLATE Latin1_General_CI_AS AS achternaam,
      CAST(t3.func_oms as VARCHAR(50)) COLLATE Latin1_General_CI_AS as functieomschrijving,
      CAST(t4.oe_vol_nm as VARCHAR(40)) COLLATE Latin1_General_CI_AS as afdeling,
      t5.opdrgvr_oms COLLATE Latin1_General_CI_AS as opdrachtgever,
         CAST(t4.kstpl_kd as INT) as kostenplaats,
         CAST(t4.oe_kort_nm as varchar(18)) COLLAte Latin1_General_CI_AS as OE_naam,
         CAST(
                CASE WHEN LEN(t4.kstpl_kd) = 6 THEN t4.kstpl_kd
                ELSE(
                    CASE WHEN LEN(t4.kstpl_kd) = 5 AND LEFT(t4.oe_kort_nm,2) = 'SO' THEN convert(int,'9'+ CONVERT(VARCHAR(10),t4.kstpl_kd))
                    ELSE convert(int,'8'+ CONVERT(VARCHAR(10),t4.kstpl_kd))
                    END)
                END
                as VARCHAR(10)) COLLATE Latin1_General_CI_AS AS nw_kostplaats,
      CAST(t2.indnst_dt as datetime) as indienst,
      CAST(t2.uitdnst_dt as datetime) as uitdienst,
         CAST(t2.arelsrt_kd as VARCHAR(10)) COLLATE Latin1_General_CI_AS as ARELSRT_OMS
      From Beaufort.dbo.DPIB010 t1
       left outer join Beaufort.dbo.DPIC300 t2 on t1.pers_nr = t2.pers_nr
              join Beaufort.dbo.DPIC351 t3 on t2.primfunc_kd = t3.func_kd
              join Beaufort.dbo.DPIB015 t4 on t2.oe_hier_sl = t4.dpib015_sl
              join beaufort.dbo.DPIC200 t5 on t2.opdrgvr_nr = t5.OPDRGVR_NR                        
      WHERE
      t2.uitdnst_dt is null AND t5.OPDRGVR_NR <> '23929' AND t5.OPDRGVR_NR <> '23843'
      OR
         t2.uitdnst_dt >= DATEADD(month, -1, GETDATE()) AND t5.OPDRGVR_NR <> '23929' AND t5.OPDRGVR_NR <> '23843'
      ) SFCM
         LEFT JOIN dbo.CostPL on SFCM.nw_kostplaats between CostPL.Val_lo AND costpl.Val_hi      

    Now here's what I need to accomplish:
    There's another table in the source DB  (Beaufort.dbo.DPIC310)  which holds  all alteration per pers_nr.  So if pers_nr 999999 has been altered 5 times it holds 5 recs with data including datetime of alteration.
    Now I need to add a column to the view which contains for every row (= pers_nr) the latest datetime from that DPIC310 table. That's DPIC310.ingang_dt.

    Here's how this table (DPIC310) could look like:

    pers_nrdv_vlgnroe_oper_sloperfunc_kdingang_dtu_versionpslot_sel
    99999911052802062017-04-01 00:00:00.000;NULL
    99999911052802062016-12-01 00:00:00.000qNULL
    99999911052802062016-05-01 00:00:00.0003NULL
    99999911052100012019-03-01 00:00:00.000#NULL
    99999911052100012019-02-01 00:00:00.000'NULL
    9999991510200012019-03-15 00:00:00.000!NULL

    So in short: I need to add a column to the view which contains at pers_nr 999999  the latest datetime from this table (=  2019-03-15 00:00:00.000)

    I did try myself but I'm afraid this is a bit beyond me. When I add a join on this table it add all the recs from this table to the view (which I can understand). But I tried to narrow down the select with MAX(ingang_dt)  but it throws me red lines.
    Anyone willing to help me with this?  Can this be done? Or maybe I need to create another view with just the data I need from this last table and then later on join them?

    Thanks in advance!

  • You might wish to disambiguate your WHERE clause before pursuing this further:

     WHERE
      t2.uitdnst_dt is null
      AND t5.OPDRGVR_NR <> '23929'
      AND t5.OPDRGVR_NR <> '23843'
      OR t2.uitdnst_dt >= DATEADD(month, -1, GETDATE())
      AND t5.OPDRGVR_NR <> '23929'
      AND t5.OPDRGVR_NR <> '23843'

    “Write the query the simplest way. If through testing it becomes clear that the performance is inadequate, consider alternative query forms.” - Gail Shaw

    For fast, accurate and documented assistance in answering your questions, please read this article.
    Understanding and using APPLY, (I) and (II) Paul White
    Hidden RBAR: Triangular Joins / The "Numbers" or "Tally" Table: What it is and how it replaces a loop Jeff Moden

  • You just need to add the table in a CROSS APPLY or OUTER APPLY and select TOP(1) with an ORDER BY date DESC
    ...
    From Beaufort.dbo.DPIB010 t1
    CROSS APPLY(SELECT TOP(1) * FROM Beaufort.dbo.DPIC310 x WHERE x.pers_nr = t1.pers_nr ORDER BY x.Date DESC) x
    left outer join Beaufort.dbo.DPIC300 t2 on t1.pers_nr = t2.pers_nr
    ...

  • Thank you very much Jonathan!
     I added the line and fieldname and no error whatsoever. So view shows data, but no additional column is showing. The query result (view) is the same as before. Since there a 'SELECT' it should, shouldn't it?

  • Super_Grover - Monday, February 25, 2019 12:19 PM

    Thank you very much Jonathan!
     I added the line and fieldname and no error whatsoever. So view shows data, but no additional column is showing. The query result (view) is the same as before. Since there a 'SELECT' it should, shouldn't it?

    I'm not sure what you mean.
    The columns in the cross apply have an alias of x. So in the sub-query you need to select a column from x
    CAST(t2.arelsrt_kd AS VARCHAR(10)) COLLATE Latin1_General_CI_AS AS ARELSRT_OMS,
    x.col1
       FROM Beaufort.dbo.DPIB010 t1
    CROSS APPLY(SELECT TOP(1) * FROM Beaufort.dbo.DPIC310 x WHERE x.pers_nr = t1.pers_nr ORDER BY x.Date DESC) x
    left outer join Beaufort.dbo.DPIC300 t2 on t1.pers_nr = t2.pers_nr

    ...

  • Jonathan AC Roberts - Monday, February 25, 2019 1:49 PM

    I'm not sure what you mean.
    The columns in the cross apply have an alias of x. So in the sub-query you need to select a column from x
    CAST(t2.arelsrt_kd AS VARCHAR(10)) COLLATE Latin1_General_CI_AS AS ARELSRT_OMS,
    x.col1
       FROM Beaufort.dbo.DPIB010 t1
    CROSS APPLY(SELECT TOP(1) * FROM Beaufort.dbo.DPIC310 x WHERE x.pers_nr = t1.pers_nr ORDER BY x.Date DESC) x
    left outer join Beaufort.dbo.DPIC300 t2 on t1.pers_nr = t2.pers_nr

    ...

    Sorry mate, you're right! I made mistake. I now have it implemented as follows and works great:

    CAST(t2.arelsrt_kd as VARCHAR(10)) COLLATE Latin1_General_CI_AS as ARELSRT_OMS,
         x.ingang_dt as MutDat
      From Beaufort.dbo.DPIB010 t1
         CROSS APPLY(SELECT TOP(1) * FROM Beaufort.dbo.DPIC310 x WHERE x.pers_nr = t1.pers_nr ORDER BY x.ingang_dt DESC) x
       left outer join Beaufort.dbo.DPIC300 t2 on t1.pers_nr = t2.pers_nr
              join Beaufort.dbo.DPIC351 t3 on t2.primfunc_kd = t3.func_kd

    Thanks very much for your help!  i honestly hadn't heard of the CROSS APPLY command before.

Viewing 6 posts - 1 through 5 (of 5 total)

You must be logged in to reply to this topic. Login to reply