Trying to utilise the technique from https://stackoverflow.com/a/123481 I'm attempting to retrieve one row for each name, with a particular sort, namely the top/first row after sorting in descending order by active, created, then prid. However the active column may contain numberic or NULL values, which is causing a duplicate in the name=bat case. Any help would be greatly appreciated.
Source table:
+------+-------+--------+---------+
| prid | name  | active | created |
+------+-------+--------+---------+
| 1    | bat   | NULL   | 3       |
| 2    | bat   | 1      | 2       |
| 3    | bat   | 2      | 1       |
| 4    | bat   | 3      | 0       |
| 5    | noise | NULL   | 2       |
| 6    | noise | NULL   | 1       |
| 7    | cup   | NULL   | 0       |
| 8    | cup   | NULL   | 0       |
| 9    | egg   | 4      | 4       |
| 10   | egg   | 4      | 2       |
+------+-------+--------+---------+
Desired result:
+------+-------+--------+---------+
| prid | name  | active | created |
+------+-------+--------+---------+
| 9    | egg   | 4      | 4       |
| 4    | bat   | 3      | 0       |
| 5    | noise | NULL   | 2       |
| 8    | cup   | NULL   | 0       |
+------+-------+--------+---------+
SQL:
SELECT p1.*
FROM source_table p1
LEFT JOIN source_table p2 ON (
  p1.name = p2.name
  AND (
    p1.active < p2.active
    OR (
      (p1.active = p2.active OR (p1.active IS NULL AND p2.active IS NULL))
      AND (
        p1.created < p2.created
        OR (
          p1.created = p2.created AND p1.prid < p2.prid
        )
      )
    )
  )
)
WHERE p2.prid IS NULL
ORDER BY p1.active DESC, p1.created DESC, p1.prid DESC
Actual result:
+------+-------+--------+---------+
| prid | name  | active | created |
+------+-------+--------+---------+
| 9    | egg   | 4      | 4       |
| 4    | bat   | 3      | 0       |
| 1    | bat   | NULL   | 3       |
| 5    | noise | NULL   | 2       |
| 8    | cup   | NULL   | 0       |
+------+-------+--------+---------+
@Gordon Linoff
Thanks for the help, I try to use the second version with the indexes (name, active, created, prid) and (active, created, prid), however it's being quite slow.
This takes 1 second, returns the right results, but in the wrong order:
SELECT t1.prid
FROM source_table t1
WHERE t1.prid = (
  SELECT t2.prid
  FROM source_table t2
  WHERE t2.name = t1.name
  ORDER BY t2.active DESC, t2.created DESC, t2.prid DESC
  LIMIT 1
)
LIMIT 50
And this takes 55 seconds:
SELECT t1.prid
FROM source_table t1
WHERE t1.prid = (
  SELECT t2.prid
  FROM source_table t2
  WHERE t2.name = t1.name
  ORDER BY t2.active DESC, t2.created DESC, t2.prid DESC
  LIMIT 1
)
ORDER BY t1.active DESC, t1.created DESC, t1.prid DESC
LIMIT 50
And really I need LIMIT 500, any ideas?
@Rick James
SQL Fiddle link: http://sqlfiddle.com/#!9/f9b39/2/0
 
     
    