Home > Back-end >  How to get the most recent record of multiple of the same records in a table while joining another t
How to get the most recent record of multiple of the same records in a table while joining another t

Time:11-18

SELECT tblSign.sigdate,tblSign.sigtime,tblSign.sigact,tblSign.esignature,tblEmpl.fname,tblEmpl.lname,tblEmpl.location, tblEmpl.estatus,tblLocs.unit,tblLocs.descript,TblLocs.addr1,tblLocs.city,tblLocs.state, tblLocs.zip
   FROM tblEmpl
   LEFT JOIN tblSign
ON tblSign.eight_id = tblEmpl.eight_id
AND tblSign.formid = '9648'
AND tblSign.sigact <> 'O'
AND tblSign.sigdate >= '2022-11-01'
LEFT JOIN tblLocs
ON tblEmpl.location = tblLocs.location
WHERE tblEmpl.estatus = 'A'
AND tblEmpl.location = '013'
ORDER BY
tblSign.sigdate ASC;

My table Sign has multiple records with the same eight_id so Im just trying to join tables getting the most recent record from tblSign besides multiple records

Data I get

Sigdate fname lname location sigact
2022-11-01 Bill Lee 023 A
2022-10-01 Bill Lee 023 A
2022-11-01 Carter Hill 555 A

This is what I want :

Sigdate fname lname location sigact
2022-11-01 Bill Lee 023 A
2022-11-01 Carter Hill 555 A

CodePudding user response:

Start by getting into better code-writing habits. Having all column names in one long string is horrible for readability and consequently troubleshooting. You can select the most recent record from a table by using a ROW_NUMBER function. I took your code, cleaned it up, added a derived table and in the derived table added a ROW_NUMBER function. I can't validate that the query works because you didn't post example source data from your tblEmpl, tblSign, and tblLocs tables. I'm not sure if the AND tblSign.sigact <> 'O' is valid in the derived table because it's not clear if you were trying to just limit the date range or that was your attempt to retrieve the most recent date.

SELECT 
    tblSign.sigdate
    , tblSign.sigtime
    , tblSign.sigact
    , tblSign.esignature
    , tblEmpl.fname
    , tblEmpl.lname
    , tblEmpl.location
    , tblEmpl.estatus,tblLocs.unit
    , tblLocs.descript
    , TblLocs.addr1
    , tblLocs.city
    , tblLocs.state
    , tblLocs.zip
FROM tblEmpl
    LEFT JOIN (
        SELECT *

            --Used to order the records for each eight_id by the date. 
            --Most recent date for each eight_id will have row_num = 1.
            , ROW_NUMBER() OVER(PARTITION BY eight_id ORDER BY sigdat DESC) as row_num
        FROM tblSign as ts
        WHERE tblSign.formid = '9648'
            AND tblSign.sigact <> 'O'
            AND tblSign.sigdate >= '2022-11-01' --Not clear if this is just to limit results or an attempt to get most recent date in the failed original code.
    ) as ts
        ON ts.eight_id = tblEmpl.eight_id
        AND ts.row_num = 1  --Use to limit to most recent date.
    LEFT JOIN tblLocs
        ON tblEmpl.location = tblLocs.location
WHERE tblEmpl.estatus = 'A'
    AND tblEmpl.location = '013'
ORDER BY
    tblSign.sigdate ASC

CodePudding user response:

You use ROW_NUMBER to get the last entry in my case for every esignature, as i thought this must be unique

WITH CTE AS
(SELECT 
    tblSign.sigdate,
    tblSign.sigtime,
    tblSign.sigact,
    tblSign.esignature,
    tblEmpl.fname,
    tblEmpl.lname,
    tblEmpl.location,
    tblEmpl.estatus,
    tblLocs.unit,
    tblLocs.descript,
    TblLocs.addr1,
    tblLocs.city,
    tblLocs.state,
    tblLocs.zip,
    ROW_NUMBER() OVER(PARTITION BY tblSign.esignature ORDER BY tblSign.sigdate DESC) rn
FROM
    tblEmpl
        LEFT JOIN
    tblSign ON tblSign.eight_id = tblEmpl.eight_id
        AND tblSign.formid = '9648'
        AND tblSign.sigact <> 'O'
        AND tblSign.sigdate >= '2022-11-01'
        LEFT JOIN
    tblLocs ON tblEmpl.location = tblLocs.location
WHERE
    tblEmpl.estatus = 'A'
        AND tblEmpl.location = '013')
SELECT     sigdate,
    sigtime,
    sigact,
    esignature,
    fname,
    lname,
    location,
    estatus,
    unit,
    descript,
    addr1,
    city,
    state,
    zip
WHERE rn = 1
ORDER BY sigdate ASC;
  • Related