Reputation: 189
I need to update the display_order column with sequence for numbers for array of ids Consider the following array of Ids (13, 6, 5, 19, 1, 3, 2), for this ids i need to update the order column
DB
+----+-------+---------------+
| id | name | display_order |
+----+-------+---------------+
| 1 | cat1 | 3 |
+----+-------+---------------+
| 2 | cat2 | 4 |
+----+-------+---------------+
| 5 | cat5 | 6 |
+----+-------+---------------+
| 6 | cat6 | 1 |
+----+-------+---------------+
| 13 | cat13 | 2 |
+----+-------+---------------+
Currently im using the following query
UPDATE categories
SET display_order = CASE id
WHEN 13 THEN 1
WHEN 6 THEN 2
WHEN 5 THEN 3
WHEN 19 THEN 4
WHEN 1 THEN 5
WHEN 3 THEN 6
WHEN 2 THEN 7
END
WHERE id IN (13, 6, 5, 19, 1, 3, 2);
Currently im looping the ids in PHP to generate the "case when" statement, the array may come with more Ids. Is there any alternative way to do it in Mysql so i can avoid looping.
Upvotes: 0
Views: 916
Reputation: 56
You can use insert into on duplicate key update.
for example:
INSERT INTO categories(id, display_order)
VALUES(13,1),
(6,2),
(5,3),
(19,4),
(1,5),
(3,6),
(2,7)
ON DUPLICATE KEY UPDATE
id = VALUES(id),
display_order = VALUES(display_order);
Upvotes: 0
Reputation: 42612
UPDATE categories
SET display_order = FIND_IN_SET(id, '13,6,5,19,1,3,2')
WHERE id IN (13, 6, 5, 19, 1, 3, 2);
Pay attention - the ids list in FIND_IN_SET
is one string literal without spaces after commas. id
is converted to string before searching, and the searching is performed as textual one.
If you want to transfer ids list into the query once you may use the next form:
UPDATE categories
CROSS JOIN ( SELECT '13,6,5,19,1,3,2' ids ) ids
SET categories.display_order = FIND_IN_SET(categories.id, ids.ids)
WHERE FIND_IN_SET(categories.id, ids.ids);
but it will be slower due to textual comparing (and hence full table scan - no indices can be used for this query). Do it on compact (less than ~1000 rows) table only.
Upvotes: 2
Reputation: 520908
You should maintain the id
values and their mappings in a separate table display_orders
:
id | val
1 | 5
2 | 7
3 | 6
5 | 3
6 | 2
13 | 1
19 | 4
Then, just do an update inner join:
UPDATE categories c
INNER JOIN display_orders d
ON d.id = c.id
SET
display_order = d.val
WHERE
c.id IN (1, 2, 3, 5, 6, 13, 19);
Upvotes: 0