0

I am in need of some inspiration for SQL design thinking, I have just started to learn SQL. My knowledge is very limited, so please bear with me..

I have a Quiz application, and in SQL, I have a whole row, corresponding with each Quiz questions and answers. It is very basic, and not designed very well. But here goes.

Like so..

enter image description here

My requirement is to give the users the ability to add a question at any point in the quiz list..So for instance, if a user would like to Add a new question at number 2, the user would be able to click the Add question at position 2, which would add a new record into the database and refresh the page to see that the questions have re-ordered and numbered..

My application pulls back the data based on Category.. So for instance if a user wants to view the History category in my application. They click a button and they are presented with the list of titles, and the below buttons..

enter image description here

As you can see.. My table is just not geared up for this.. Can anybody give me some tips, on how i could achieve this within the DB.

Many thanks.

sinfella
  • 246
  • 2
  • 19
  • 1
    Just throwing an idea. You can create another table with the id of the question and InOrder column. When you add a new question, you can update InOrder values of other questions. After that you can order questions by joining your question table and order table and use InOrder column as a sorting column. – MonkeyDLuffy Feb 04 '21 at 22:22
  • What is the actual problem here? Ordering the questions? Presenting consecutive ordinals (but probably for an arbitrary order)? Or knowing which question to delete/change/whatever when a button is pressed? – sticky bit Feb 04 '21 at 22:26
  • 1
    And still (I know that from somewhere, did you post something about that schema yesterday?) you might want to revise the schema and instead of columns for the answers you may make an extra table with one row per answer. – sticky bit Feb 04 '21 at 22:29
  • Thanks for the suggestions guys – sinfella Feb 04 '21 at 22:30
  • @MonkeyDLuffy, i feel that is the right way to go, i just wouldn't know how to update the other fields based on the new InOrder value added to the questionId. Do you have an example? – sinfella Feb 04 '21 at 22:33
  • I can do updates, but only the simple ones, updating per row. Not sure how i would update the rest of the fields – sinfella Feb 04 '21 at 22:34
  • @stickybit thank you for the response, the problem is at the moment, my list is coming in which ever order the questions were created first. I need to have the ability to place a new question, anywhere in that list. If that makes sense. I was just a bit stuck with the understanding on how to achieve this, with very minimal SQL knowledge. – sinfella Feb 04 '21 at 22:37
  • You might get some ideas from [this](https://stackoverflow.com/a/48329605/92546) and [this](https://stackoverflow.com/a/15858191/92546) answer. A quiz might be better represented by `Quizzes` (`QuizId`, `QuizTitle`, `CategoryId`), `Questions` (`QuestionId`, `QuizId`, `QuestionOrder`, `Question`, `CorrectAnswerId`), and `Answers` (`AnswerId`, `QuestionId`, `AnswerOrder`, `Answer` ) – HABO Feb 04 '21 at 22:58

2 Answers2

1

One possible solution is to create one table for the questions. and one for the categories.

CREATE TABLE question
             (id integer,
              question varchar(64),
              PRIMARY KEY (id));

CREATE TABLE category
             (id integer,
              name varchar(64),
              PRIMARY KEY (id));

And then a table that links questions to categories with an ordinal that designates the position of the question in the category. That also has the charm that a question can be in more than one category.

CREATE TABLE category_question
             (category integer,
              question integer,
              ordinal integer,
              PRIMARY KEY (category,
                           question),
              FOREIGN KEY (category)
                          REFERENCES category
                                     (id),
              FOREIGN KEY (question)
                          REFERENCES question
                                     (id));

And, as I already suggested, an extra table for the answers, also with an ordinal.

CREATE TABLE answer
             (id integer,
              question integer,
              answer varchar(64),
              ordinal integer,
              PRIMARY KEY (id),
              FOREIGN KEY (answer)
                          REFERENCES question
                                     (id));

Whenever a question (or answer) is moved, you can change the ordinals accordingly. For display purposes you can order by it.

sticky bit
  • 36,626
  • 12
  • 31
  • 42
  • Thank you for the demo, can you supply any SP's for inserting and the fetching of the data if possible. – sinfella Feb 05 '21 at 01:18
1

You want a Linked List for the ids and external table for the category (sticky bit handled this already).

When inserting your new row used a stored proc that does something like this:

update QuizTable set position = position + 1 where position >= 2;
insert into QuizTable(position, question) values (2, "new question");

If your table requires concurrent updates then this will not work of course!! (as you could get locking if one user updates position 8 while you update position 2.

The only way to do this safely for a multi user system would be to implement next/prior columns (or put them in a separate database table). This option is a difficult task and you should probably avoid it.

Your insert stored procedure would look something like this:

declare @myNewId = 94;
declare @position2Id = 50;
insert into QuizTable(id, question)
values (@myNewId, "my new question");

declare @next, @prior
select @next = next, @prior = prior from QuizTable where id = @myNewId;

update QuizTable set next = @myNewId where id = prior;
update QuizTable set prior = @myNewId where id = @position2Id

Then your list will be made up of a dynamically calculated id and a self referenced table scan where id 1 = prior IS NULL id 2 = id1.next

Just found this link for you: Linked List in SQL

Jon P
  • 117
  • 4
  • Sorry, that looks really complicated for a newbie, can you explain in simple terms, what is happening in these queries. thank you – sinfella Feb 05 '21 at 01:16
  • Thanks guys for your help, i have followed the linked list link and its worked, thanks all for your help – sinfella Feb 05 '21 at 09:49