0

I've an SQL statement that I've been dealing with for a while now.

How do I get the most recent (by date, and then id) weight-value from another table. This is my query so far:

SELECT e.name, e.picture_url, e.id AS exercise_id, w.parent_id, e.video_url,
        w.id, w.comment, w.time, w.reps, w.rest, w.sets, wt.name as wtype,
        w.order_by, mg.name as muscle_group, eq.name as equipment, w_track.*
        FROM workout w
        LEFT JOIN exercises e
        ON e.id = w.exercise_id
        LEFT JOIN workout_types wt
        ON wt.id = e.workout_type_id
        LEFT JOIN muscle_groups mg
        ON e.muscle_group_id = mg.id
        LEFT JOIN equipments eq
        ON eq.id = e.equipment_id

        LEFT JOIN (SELECT workout_id, weight FROM workout_tracking GROUP BY workout_id ORDER BY date DESC, id DESC) w_track
        ON w.id = w_track.workout_id


        WHERE workout_day_id = 395

I want to left join workout_tracking and get the most recent 'weight' value - the row with the newest date and highest id.

Thanks in advance! All help appreciated!

UPDATE When I run the above query I get some random 'weight' number, and not the most recent one.

The 'workout' table consists of: - id (primary key for workout_tracking) - workout_day_id (foreign key for 'workout_day' - reps - rest - sets - etc...

The 'workout_tracking' table consists of: - id - workout_id (workout-table foreign key) - weight - date

Sample data 'workout'-table:

  +---+------------+-------------+
  |id |     sets   |    reps     |
  +---+------------+-------------+
  | 1 |      3     |     10

'workout_tracking'-table:

  +---+------------+-------------+-------------+
  |id | workout_id |    weight   |    date
  +---+------------+-------------+-------------+
  | 1 |      1     |     10        2017-05-22
    2        1           12        2017-05-28
    3        1           14        2017-05-28
    4        1           11        2017-05-28
    5        1          NULL       2017-05-28
    6        1          NULL       2017-05-28
Mathias Lund
  • 752
  • 1
  • 9
  • 23

2 Answers2

1

The easy way is using variables:

SQL DEMO

SELECT `id`, `workout_id`, `weight`, `date`,
       @rn := IF( @workout_id = `workout_id`,
                  @rn + 1,
                  IF(@workout_id := `workout_id`, 1, 1)
                ) as rn
FROM workout_tracking     
CROSS JOIN (SELECT @rn := 0, @workout_id := -1) as var
ORDER BY `workout_id`, `date` DESC, `id` DESC

Because you order first for workout_id you can find the latest date and latest id, in this case those will have @rn = 1

Now your final query should be

SELECT w.*, filter.*
FROM workout w
JOIN (SELECT `id`, `workout_id`, `weight`, `date`,
              @rn := IF( @workout_id = `workout_id`,
                         @rn + 1,
                         IF(@workout_id := `workout_id`, 1, 1)
                       ) as rn
      FROM workout_tracking     
      CROSS JOIN (SELECT @rn := 0, @workout_id := -1) as var
      ORDER BY `workout_id`, `date` DESC, `id` DESC
     ) as filter
 ON w.id = filter.`workout_id`
WHERE filter.rn = 1;

For LEFT JOIN try:

LEFT JOIN ( ... ) as filter
  ON w.id = filter.`workout_id`
 AND filter.rn = 1

dont need the where condition.

Juan Carlos Oropeza
  • 47,252
  • 12
  • 78
  • 118
0

LEFT JOIN (SELECT MAX(workout_id) AS workout_id, weight FROM workout_tracking GROUP BY workout_id ORDER BY date DESC, id DESC) w_track ON w.id = w_track.workout_id

zarif khan
  • 81
  • 6