sql >> データベース >  >> RDS >> Mysql

テーブル内のフィールドによる動的な順序付けをどのように制御しますか?

    私があなたの言うことを正しく理解しているなら、positionの値のシーケンスを適切に管理する方法が必要です 新しい質問を挿入するとき、既存の質問の位置を変更するとき、または質問を削除するときの列。

    質問テーブルの次のDDLがあるとします:

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

    このような初期データセット

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

    質問の順序付きリストを取得するには あなたは明白です

    SELECT * 
      FROM questions 
     ORDER BY position;
    

    質問リストの最後に新しい質問を挿入するには あなたは

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

    結果は次のようになります:

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

    特定の位置に新しい質問を挿入するには (3番目の位置にしましょう)リストでは、2つのクエリでそれを行います:

    UPDATE questions
       SET position = position + 1
     WHERE position >= 3;
    
    INSERT INTO questions (question, position) 
    VALUES ('Another Question', 3);
    

    これで

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

    2つの質問の位置を入れ替える (例:ID 2と5の質問)あなたは

    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
    

    私たちが持っているものを見てみましょう

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

    これは、ユーザーが上下のボタンをクリックして正しい質問IDを入力したときに行うこととまったく同じです。

    これで、質問を削除するときにギャップのない位置シーケンスを維持したい場合は、それを行うことができます。

    リストの最後から削除するには 単純な削除を使用します

    DELETE FROM questions WHERE id=4;
    

    結果

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

    リストの途中(または先頭)にある質問を削除する より多くの作業が必要です。 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;
    

    そして最後に

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

    更新 :私たちの生活を楽にするために、すべてをストアドプロシージャでラップできます

    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 ;
    

    次のように使用します:

    -- 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. 動的な.htaccessファイルを作成できますか?

    2. PHPボタンを使用してテーブルをCSVにエクスポートする

    3. .csvファイルをOracleFormsアプリケーションにインポートする

    4. 参照データパターン:拡張可能で柔軟