简体   繁体   中英

MYSQL - Two tables get record from second table last tracked row for each user

I have two tables

Table A has usr_id , usr_name , usr_status [1 or 0]

Table B has id, usr_id,tracked_date [Each user can track multiple time]

Need to get the last track of each user has usr_status = 1

How to achieve through MySQL query?

Tried like:

SELECT 
    *
FROM
    tableb b
        LEFT JOIN
    tablea a ON a.usr_id = b.usr_id
GROUP BY a.usr_id

Please advice ?

  • In a Derived table, get the maximum value of tracked_date for every usr_id
  • Join this result-set back to the main tables, to get the corresponding row(s).

Try:

SELECT 
  ta.*, tb.* 
FROM 
  tablea AS ta 
JOIN tableb AS tb 
  ON tb.user_id = ta.usr_id 
JOIN (
      SELECT 
        user_id, 
        MAX(tracked_date) AS max_tracked_date 
      FROM tableb
      GROUP BY user_id
     ) AS dt 
  ON dt.usr_id = tb.usr_id AND 
     dt.max_tracked_date = tb.tracked_date 
WHERE ta.usr_status = 1

In MySQL version (8.0.2 and above), we can use Window Functions . Using Row_Number() we can set row number to 1 for the row with highest tracked_date value, in a partition of usr_id . Now, we can use this as a Derived Table and consider only those rows where row number is equal to 1.

SELECT 
  dt.* 
FROM 
(
  SELECT
    ta.*, 
    tb.*, 
    ROW_NUMBER() OVER (PARTITION BY ta.usr_id 
                       ORDER BY tb.tracked_date DESC) AS row_no 
  FROM 
    tablea AS ta 
  JOIN tableb AS tb ON tb.usr_id = ta.usr_id 
  WHERE ta.usr_status = 1
) AS dt 
WHERE dt.row_no = 1

Additional: If you are looking to get all users ( status = 1 ), but no tracked_date entry yet; a straight LEFT JOIN will not work between the tables and the Derived Table.

We will have to first get the complete row corresponding to maximum tracked_date in a separate Derived Table; and then do a LEFT JOIN from the users table, to get all users.

SELECT
ta.*, dt2.* 
FROM
  tablea AS ta
LEFT JOIN 
(SELECT tb.*, 
        dt.max_tracked_date
 FROM tableb AS tb
 JOIN (
       SELECT
         usr_id,
         MAX(tracked_date) AS max_tracked_date
       FROM tableb
       GROUP BY usr_id
      ) AS dt
   ON (dt.usr_id = tb.usr_id AND
       dt.max_tracked_date = tb.tracked_date) 
) AS dt2 ON ta.usr_id = dt2.usr_id  
WHERE ta.usr_status = 1

RESULT

| usr_id | usr_name | usr_status | id  | usr_id | stage | tracked_date        | max_tracked_date    |
| ------ | -------- | ---------- | --- | ------ | ----- | ------------------- | ------------------- |
| 1      | john     | 1          | 2   | 1      | 2     | 2018-11-12 13:12:12 | 2018-11-12 13:12:12 |
| 2      | dave     | 1          | 3   | 2      | 1     | 2018-11-12 13:12:12 | 2018-11-12 13:12:12 |
| 3      | smith    | 1          |     |        |       |                     |                     |

View on DB Fiddle

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM