sql >> Database >  >> RDS >> Mysql

Hoe controleren we dynamische ordening door een veld in een tabel?

Als ik je goed begrijp, heb je een manier nodig om de reeks waarden in position goed te beheren kolom wanneer u nieuwe vragen invoegt, de positie van een bestaande wijzigt of vragen verwijdert.

Stel dat u de volgende DDL van uw vragentabel heeft:

CREATE TABLE `questions` (
    `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
    `question` VARCHAR(256) DEFAULT NULL,
    `position` INT(11) DEFAULT NULL,
    PRIMARY KEY (`id`)
);

en initiële dataset zoals deze

+----+------------+----------+
| id | question   | position |
+----+------------+----------+
|  1 | Question 1 |        1 |
|  2 | Question 2 |        2 |
|  3 | Question 3 |        3 |
+----+------------+----------+

Om een ​​geordende lijst met vragen te krijgen je doet duidelijk

SELECT * 
  FROM questions 
 ORDER BY position;

Een nieuwe vraag invoegen aan het einde van de vragenlijst jij wel

INSERT INTO questions (question, position) 
SELECT 'New Question', COALESCE(MAX(position), 0) + 1
  FROM questions;

Het resultaat is:

+----+--------------+----------+
| id | question     | position |
+----+--------------+----------+
|  1 | Question 1   |        1 |
|  2 | Question 2   |        2 |
|  3 | Question 3   |        3 |
|  4 | New Question |        4 |
+----+--------------+----------+

Een nieuwe vraag invoegen op een specifieke positie (laten we zeggen naar positie 3) in de lijst doe je het met twee queries:

UPDATE questions
   SET position = position + 1
 WHERE position >= 3;

INSERT INTO questions (question, position) 
VALUES ('Another Question', 3);

Nu heb je

+----+------------------+----------+
| id | question         | position |
+----+------------------+----------+
|  1 | Question 1       |        1 |
|  2 | Question 2       |        2 |
|  5 | Another Question |        3 |
|  3 | Question 3       |        4 |
|  4 | New Question     |        5 |
+----+------------------+----------+

Om posities van twee vragen om te wisselen (bijv. vragen met id 2 en 5) doe je

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

Laten we eens kijken wat we hebben

+----+------------------+----------+
| id | question         | position |
+----+------------------+----------+
|  1 | Question 1       |        1 |
|  5 | Another Question |        2 |
|  2 | Question 2       |        3 |
|  3 | Question 3       |        4 |
|  4 | New Question     |        5 |
+----+------------------+----------+

Dat is precies wat u doet wanneer de gebruiker op uw omhoog- en omlaagknoppen klikt en de juiste vraag-ID's invoert.

Als je de volgorde van je posities wilt behouden zonder gaten wanneer je een vraag verwijdert, kun je dat doen.

Wissen aan het einde van de lijst je gebruikt eenvoudig verwijderen

DELETE FROM questions WHERE id=4;

Resultaten

+----+------------------+----------+
| id | question         | position |
+----+------------------+----------+
|  1 | Question 1       |        1 |
|  5 | Another Question |        2 |
|  2 | Question 2       |        3 |
|  3 | Question 3       |        4 |
+----+------------------+----------+

Een vraag in het midden (of aan het begin) van de lijst verwijderen vereist meer werk. Laten we zeggen dat we de vraag met id=5

. willen verwijderen
-- 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;

En tot slot hebben we

+----+--------------+----------+
| id | question     | position |
+----+--------------+----------+
|  1 | Question 1   |        1 |
|  2 | Question 2   |        2 |
|  3 | Question 3   |        3 |
+----+--------------+----------+

UPDATE :Om ons leven gemakkelijker te maken, kunnen we alles in opgeslagen procedures inpakken

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 ;

en gebruik ze als volgt:

-- 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);



  1. mySQL selecteer IN bereik

  2. Fout bij verbinden met database:(bij gebruik van klasse org.gjt.mm.mysql.Driver)

  3. MySQL-tabellen overschrijven met AWS Glue

  4. MySQL my.ini-locatie