Here\'s a question I\'ve been racking my brain over. Let\'s say I have a table that has a series of timestamps and a part number as the primary key. The table stores incremental
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
;
ruakh is right. Alternative: Write a user-defined aggregate using SQL-CLR. This aggregate can run bottom-top-top over your rows and remember the first non-null value of each column.
You can also do this in the application. Make your program request rows in sorted order in batches of, say, 10 rows. Aggregate these batches like described above. If after the current batch is done a null-column is there get the next batch.
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
list of relevant timestamps:
select max timestamp from part_changes where x_POS is not null group by part
You can make this a view: lets call this view1
SELECT part_changes.part, part_changes.x-pos
FROM part_changes left join view1 on part_changes.part = view1.part
WHERE x-pos IS NOT NULL
AND part_changes.timestamp = view1.timestamp
GROUP BY part_changes.part
See where I am going? That should give you the full list for x-pos.