Database: Select last non-null entries
For only one part this should give you an answer .. thanks to ruakh
But I dont like this version ..
SELECT
(SELECT timestamp FROM part_changes WHERE part = $part
ORDER BY timestamp DESC
LIMIT 1) as timestamp,
(SELECT x-pos FROM part_changes WHERE part = $part and x-pos IS NOT NULL
ORDER BY timestamp DESC
LIMIT 1) as xpos,
(SELECT y-pos FROM part_changes WHERE part = $part and y-pos IS NOT NULL
ORDER BY timestamp DESC
LIMIT 1) as ypos,
(SELECT status FROM part_changes WHERE part = $part and status IS NOT NULL
ORDER BY timestamp DESC
LIMIT 1)) as status
Rather than using a UNION
, it sounds like you really want subqueries in the field list. That is, instead of (SELECT ...) UNION (SELECT ...) UNION (SELECT ...)
, you want SELECT (SELECT ...), (SELECT ...), (SELECT ...)
.
For example:
SELECT part,
( SELECT x_pos
FROM part_changes
WHERE part = pc.part
AND x_pos IS NOT NULL
ORDER
BY timestamp DESC
LIMIT 1
) AS x_pos,
( SELECT y_pos
FROM part_changes
WHERE part = pc.part
AND y_pos IS NOT NULL
ORDER
BY timestamp DESC
LIMIT 1
) AS y_pos,
( SELECT status
FROM part_changes
WHERE part = pc.part
AND status IS NOT NULL
ORDER
BY timestamp DESC
LIMIT 1
) AS status
FROM ( SELECT DISTINCT
part
FROM part_changes
) AS pc
;
But at this point I would really consider writing a stored procedure.
Alternatively:
SELECT DISTINCT
part,
FIRST_VALUE(x_pos) OVER
( PARTITION BY part
ORDER BY CASE WHEN x_pos IS NULL
THEN NULL
ELSE TIMESTAMP
END DESC NULLS LAST
) AS x_pos,
FIRST_VALUE(y_pos) OVER
( PARTITION BY part
ORDER BY CASE WHEN y_pos IS NULL
THEN NULL
ELSE TIMESTAMP
END DESC NULLS LAST
) AS y_pos,
FIRST_VALUE(status) OVER
( PARTITION BY part
ORDER BY CASE WHEN status IS NULL
THEN NULL
ELSE TIMESTAMP
END DESC NULLS LAST
) AS status
FROM part_changes
;