So i have this table:
req_num | number | status | order |
---|---|---|---|
1254 | 5 | 7 | 1 |
1254 | 4 | 7 | 2 |
1254 | 6 | 7 | 3 |
1246 | 7 | 8 | 1 |
1246 | 5 | 8 | 2 |
1246 | 3 | 8 | 3 |
1253 | 1 | 9 | 1 |
1253 | 4 | 7 | 2 |
1253 | 7 | 4 | 3 |
1321 | 7 | 4 | 1 |
1321 | 8 | 4 | 2 |
1321 | 7 | 4 | 3 |
1321 | 8 | 4 | 4 |
and i need to know if theres a way to generate a query that get a column like this based on the highest value in the "order" column.
req_num | number | status | order | last_req |
---|---|---|---|---|
1254 | 5 | 7 | 1 | not_last |
1254 | 4 | 7 | 2 | not_last |
1254 | 6 | 7 | 3 | last |
1246 | 7 | 8 | 1 | not_last |
1246 | 5 | 8 | 2 | not_last |
1246 | 3 | 8 | 3 | last |
1253 | 1 | 9 | 1 | not_last |
1253 | 4 | 7 | 2 | not_last |
1253 | 7 | 4 | 3 | last |
1321 | 7 | 4 | 1 | not_last |
1321 | 8 | 4 | 2 | not_last |
1321 | 7 | 4 | 3 | not_last |
1321 | 8 | 4 | 4 | last |
this table doesnt have any ids and i can't do inserts on it, any ideas?
CodePudding user response:
You can use window
functions to accomplish this - you can partition your data by req_num
and then take the item in each partition with the highest order
.
The docs: https://dev.mysql.com/doc/refman/8.0/en/window-functions-frames.html
The result will be something like (untested):
SELECT rec_num, number, status, LAST_VAL(order) OVER w AS 'last',
FROM my_table
WINDOW w AS (PARTITION BY req_num ORDER BY order);
That won't give you exactly what you want as all the rows will now include the highest order num for that rec_num. But you can then easily compare the order
and last
columns to create your last
and not_last
identifiers.
SELECT rec_num, number, status, LAST_VAL(order) OVER w AS 'last',
IF(`order` = `last`, 'last', 'not_last') AS last_req
FROM my_table
WINDOW w AS (PARTITION BY req_num ORDER BY order);
The window functions are remarkably powerful for situations like this.
CodePudding user response:
In order to solve this problem, you need to look for the maximum value in the order
field, grouped by req_num.
If your version is MySQL 8.0, you can use the ROW_NUMBER
window function to assign an ordinal value to that column in a descendent way, so that your max value has ranking = 1. Afterwards you check with an IF
statement if your column has the value 1 or not, and replace with 'last' and 'not_last' accordingly.
SELECT tab.req_num,
tab.status,
tab.order,
IF(max_values.max_order, 'last', 'not_last') AS last_req
FROM tab
LEFT JOIN (SELECT req_num,
MAX(order) AS max_order
FROM tab
GROUP BY req_num ) max_values
ON tab.req_num = max_values.req_num
AND tab.order = max_values.max_order
Demo here.
If your version is MySQL 5.X, you can first use the MAX
aggregation function in a subquery containing only req_num
and order
, by grouping on the former field and aggregating on the latter one. Then you can LEFT JOIN
the original table with this result set, and the order
values who will have assigned NULL will be the ones that are 'not_last'.
SELECT tab.req_num,
tab.status,
tab.order,
IF(max_values.max_order, 'last', 'not_last') AS last_req
FROM tab
LEFT JOIN (SELECT req_num_,
MAX(order) AS max_order
FROM tab
GROUP BY req_num ) max_values
ON tab.req_num = max_values.req_num
AND tab.order = max_values.max_order
Demo here.