Jika saya mengerti Anda benar, Anda memerlukan cara untuk mengelola urutan nilai dengan benar di position
kolom saat Anda memasukkan pertanyaan baru, mengubah posisi pertanyaan yang sudah ada, atau menghapus pertanyaan.
Katakanlah Anda telah mengikuti DDL dari tabel pertanyaan Anda:
CREATE TABLE `questions` (
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`question` VARCHAR(256) DEFAULT NULL,
`position` INT(11) DEFAULT NULL,
PRIMARY KEY (`id`)
);
dan kumpulan data awal seperti ini
+----+------------+----------+
| id | question | position |
+----+------------+----------+
| 1 | Question 1 | 1 |
| 2 | Question 2 | 2 |
| 3 | Question 3 | 3 |
+----+------------+----------+
Untuk mendapatkan daftar pertanyaan yang berurutan kamu jelas
SELECT *
FROM questions
ORDER BY position;
Untuk menyisipkan pertanyaan baru ke akhir daftar pertanyaan kamu bisa
INSERT INTO questions (question, position)
SELECT 'New Question', COALESCE(MAX(position), 0) + 1
FROM questions;
Hasilnya adalah:
+----+--------------+----------+
| id | question | position |
+----+--------------+----------+
| 1 | Question 1 | 1 |
| 2 | Question 2 | 2 |
| 3 | Question 3 | 3 |
| 4 | New Question | 4 |
+----+--------------+----------+
Untuk menyisipkan pertanyaan baru ke posisi tertentu (misalkan ke posisi 3) dalam daftar Anda melakukannya dengan dua pertanyaan:
UPDATE questions
SET position = position + 1
WHERE position >= 3;
INSERT INTO questions (question, position)
VALUES ('Another Question', 3);
Sekarang Anda memiliki
+----+------------------+----------+
| id | question | position |
+----+------------------+----------+
| 1 | Question 1 | 1 |
| 2 | Question 2 | 2 |
| 5 | Another Question | 3 |
| 3 | Question 3 | 4 |
| 4 | New Question | 5 |
+----+------------------+----------+
Untuk menukar posisi dua pertanyaan (mis. pertanyaan dengan ID 2 dan 5) Anda melakukannya
UPDATE questions AS q1 INNER JOIN
questions AS q2 ON q1.id = 2 AND q2.id = 5
SET q1.position = q2.position,
q2.position = q1.position
Mari kita lihat apa yang kita punya
+----+------------------+----------+
| id | question | position |
+----+------------------+----------+
| 1 | Question 1 | 1 |
| 5 | Another Question | 2 |
| 2 | Question 2 | 3 |
| 3 | Question 3 | 4 |
| 4 | New Question | 5 |
+----+------------------+----------+
Itulah yang Anda lakukan ketika pengguna mengklik tombol atas dan bawah Anda, memberikan id pertanyaan yang benar.
Sekarang jika Anda ingin menjaga urutan posisi Anda tanpa celah saat Anda menghapus pertanyaan, Anda dapat melakukannya.
Untuk menghapus dari akhir daftar Anda menggunakan penghapusan sederhana
DELETE FROM questions WHERE id=4;
Hasil
+----+------------------+----------+
| id | question | position |
+----+------------------+----------+
| 1 | Question 1 | 1 |
| 5 | Another Question | 2 |
| 2 | Question 2 | 3 |
| 3 | Question 3 | 4 |
+----+------------------+----------+
Menghapus pertanyaan di tengah (atau awal) daftar membutuhkan lebih banyak pekerjaan. Katakanlah kita ingin menghapus pertanyaan dengan id=5
-- Get the current position of question with id=5
SELECT position FROM questions WHERE id=5;
-- Position is 2
-- Now delete the question
DELETE FROM questions WHERE id=5;
-- And update position values
UPDATE questions
SET position = position - 1
WHERE position > 2;
Dan akhirnya kita memiliki
+----+--------------+----------+
| id | question | position |
+----+--------------+----------+
| 1 | Question 1 | 1 |
| 2 | Question 2 | 2 |
| 3 | Question 3 | 3 |
+----+--------------+----------+
PERBARUI :Untuk membuat hidup kita lebih mudah, kita dapat membungkus semuanya dalam prosedur tersimpan
DELIMITER $$
CREATE PROCEDURE add_question (q VARCHAR(256), p INT)
BEGIN
IF p IS NULL OR p = 0 THEN
INSERT INTO questions (question, position)
SELECT q, COALESCE(MAX(position), 0) + 1
FROM questions;
ELSE
UPDATE questions
SET position = position + 1
WHERE position >= p;
INSERT INTO questions (question, position)
VALUES (q, p);
END IF;
END$$
DELIMITER ;
DELIMITER $$
CREATE PROCEDURE swap_questions (q1 INT, q2 INT)
BEGIN
UPDATE questions AS qs1 INNER JOIN
questions AS qs2 ON qs1.id = q1 AND qs2.id = q2
SET qs1.position = qs2.position,
qs2.position = qs1.position;
END$$
DELIMITER ;
DELIMITER $$
CREATE PROCEDURE delete_question (q INT)
BEGIN
SELECT position INTO @cur_pos FROM questions WHERE id=q;
SELECT MAX(position) INTO @max FROM questions;
DELETE FROM questions WHERE id=q;
IF @cur_pos <> @max THEN
UPDATE questions
SET position = position - 1
WHERE position > @cur_pos;
END IF;
END$$
DELIMITER ;
dan gunakan seperti ini:
-- Add a question to the end of the list
CALL add_question('How are you today?', 0);
CALL add_question('How are you today?', NULL);
-- Add a question at a specific position
CALL add_question('How do you do today?', 3);
-- Swap questions' positions
CALL swap_questions(1, 7);
-- Delete a question
CALL delete_question(2);