Внесение изменений в несколько записей на основе изменения одной записи с помощью SQL

mysql node.js

144 просмотра

3 ответа

383 Репутация автора

У меня есть таблица продуктов. У них есть поле «Позиция», которое представляет порядок, в котором они должны отображаться в списке (listID - это список, в котором они находятся, мы не хотим переупорядочивать элементы в другом списке).

+--id--+--listID--+---name---+--position--+
|   1  |     1    | cheese   |      0     |
|   2  |     1    | chips    |      1     |
|   3  |     1    | bacon    |      2     |
|   4  |     1    | apples   |      3     |
|   5  |     1    | pears    |      4     |
|   6  |     1    | pie      |      5     |
|   7  |     2    | carrots  |      0     |
| 8,9+ |    3,4+  | ...      |     ...    |
+------+----------+----------+------------+

Я хочу иметь возможность сказать «Переместить груши в до фишек», что предполагает установку позиции Пирса в положение 1, а затем увеличение всех позиций между ними на 1., чтобы полученная в результате таблица выглядела следующим образом ...

+--id--+--listID--+---name---+--position--+
|   1  |     1    | cheese   |      0     |
|   2  |     1    | chips    |      2     |
|   3  |     1    | bacon    |      3     |
|   4  |     1    | apples   |      4     |
|   5  |     1    | pears    |      1     |
|   6  |     1    | pie      |      5     |
|   7  |     2    | carrots  |      0     |
| 8,9+ |    3,4+  | ...      |     ...    |
+------+----------+----------+------------+

Так что все, что мне нужно сделать, это SELECT name FROM mytable WHERE listID = 1 ORDER BY positionи я получу всю свою еду в правильном порядке.

Можно ли сделать это с помощью одного запроса? Помните, что запись может перемещаться вверх или вниз по списку и что таблица содержит записи для нескольких списков, поэтому нам нужно изолировать listID.

Мои знания SQL довольно ограничены, поэтому сейчас единственный способ, которым я знаю, чтобы сделать это, состоит в том, чтобы SELECT id, position FROM mytable WHERE listID = 1 AND position BETWEEN 1 AND 5затем я мог использовать Javascript (node.js), чтобы изменить положение с 5 на 1, и увеличить все остальные +1. Затем ОБНОВИТЬ все записи, которые я только что изменил.

Просто каждый раз, когда я пытаюсь прочитать что-то о SQL, все говорят, что нужно избегать множественных запросов и избегать синхронного кодирования и тому подобного.

Спасибо

Автор: tyler mackenzie Источник Размещён: 16.11.2016 02:32

Ответы (3)


1 плюс

43313 Репутация автора

Это требует сложного запроса, который обновляет много записей. Но небольшое изменение в ваших данных может изменить положение вещей, так что это может быть достигнуто с помощью простого запроса, который изменяет только одну запись.

UPDATE my_table set position = position*10;

В старые времена язык программирования BASIC во многих системах имел номера строк, это поощряло использование кода spagetti. Вместо функций многие люди писали GOTO line_number. Реальная проблема возникла, если вы последовательно пронумеровали строки и вам пришлось добавить или удалить несколько строк. Как люди обошли это? Приращением строки на 10! Это то, что мы делаем здесь.

Итак, вы хотите, чтобы груши были вторым предметом?

UPDATE my_table set position = 15 WHERE listId=1 AND name = 'Pears'

Обеспокоены тем, что в итоге промежутки между предметами исчезнут после многократного переупорядочения? Не бойся просто делай

UPDATE my_table set position = position*10;

Временами.

Автор: e4c5 Размещён: 16.11.2016 05:53

0 плюса

383 Репутация автора

Я в основном выяснил свою проблему. Поэтому я решил разместить здесь ответ, если кто-нибудь посчитает его полезным. Я могу использовать оператор CASE в SQL. Также с помощью Javascript заранее для создания моего SQL-запроса я могу изменить несколько записей.

Это строит мой SQL-запрос:

var sql;
var incrementDirection = (startPos > endPos)? 1 : -1;
sql = "UPDATE mytable SET position = CASE WHEN position = "+startPos+" THEN "+endPos;
for(var i=endPos; i!=startPos; i+=incrementDirection){
    sql += " WHEN position = "+i+" THEN "+(i+incrementDirection);
}
sql += " ELSE position END WHERE listID = "+listID;

Если я хочу переместить груши, прежде чем чипсы. Я могу установить:

startPos = 4;
endPos = 1;
listID = 1;

Мой код будет производить SQL-оператор, который выглядит следующим образом:

UPDATE mytable
SET position = CASE
  WHEN position = 4 THEN 1
  WHEN position = 1 THEN 2
  WHEN position = 2 THEN 3
  WHEN position = 3 THEN 4
  ELSE position
END
WHERE listID = 1

Я запускаю этот код, и моя финальная таблица будет выглядеть так:

+--id--+--listID--+---name---+--position--+
|   1  |     1    | cheese   |      0     |
|   2  |     1    | chips    |      2     |
|   3  |     1    | bacon    |      3     |
|   4  |     1    | apples   |      4     |
|   5  |     1    | pears    |      1     |
|   6  |     1    | pie      |      5     |
|   7  |     2    | carrots  |      0     |
| 8,9+ |    3,4+  | ...      |     ...    |
+------+----------+----------+------------+

После этого все, что мне нужно сделать, это запустить, SELECT name FROM mytable WHERE listID = 1 ORDER BY positionи результат будет следующим:

cheese
pears
chips
bacon
apples
pie
Автор: tyler mackenzie Размещён: 19.11.2016 04:01

1 плюс

904 Репутация автора

Я не думаю, что это удобно сделать менее чем за два запроса, и это нормально, должно быть как можно меньше запросов, но не любой ценой. Эти два запроса будут похожи (основываясь на том, что вы пишете сами)

UPDATE mytable SET position = 1 WHERE listID = 1 AND name = 'pears';
UPDATE mytable SET position = position + 1 WHERE listID = 1 AND position BETWEEN 2 AND 4;
Автор: comodoro Размещён: 19.11.2016 04:02
Вопросы из категории :
32x32