Storing user created folders in SQL database - sql

I am a high school student building an app for students in my school to store their grades and help with their organisation overall. In this app the users can create folders and add grades to these folders. I am using a SQL database for storing the grades. My database currently looks something like this:
I have two tables to store the information, the first one is for the subjects like this:
UserID
ID
DisplayName
ParentID
abcd
1
English
null
defg
2
Vocabulary
1
...
...
...
...
Note that the ParentID is either the ID of another folder to create nested folders, or null.
A table for the grades:
UserID
ID
FolderID
Grade
DisplayName
abcd
1
1
A
Grammar Test
defg
2
2
B
Vocabulary pages 12-13
...
...
...
...
...
Here the FolderID refers to a folder from the table above.
As well as a table for the users:
UserID
FirstName
LastName
Email
Password
abcd
Alice
Smith
alice.smith#example.com
$$
defg
Bob
Brown
bob.brown#example.com
$$
...
...
...
...
...
Upon creating an account the user can decide to either chose a configuration template or skip this step. When he chooses a template he is prompted to choose his subjects from a few options (for example you can choose the second language between German and Italian). And these folders then get created and added to the database.
I now want to store the choices the user made to do some data analysis with it. The problem is that I want the user to be able to edit the folder name if he wants to... A nice bonus would be if I could translate the folders using i18n.
I have thought about creating a new table with all possible subjects, each getting a new id which is a prime number so I can multiply them to store the users unique configuration as well as creating a new column in the table for the SubjectID in the tables and query all the folders from a user. Would this be a good idea?
Do you have any other suggestions for me? (this is my first project of this size and I am happy for all feedback)

I would change the approach. I would have a table for subjects of the format of:
subjects(id, parentID, displayName)
and there would be a many-to-many relation for subject-user, like
user_subjects(id, userID, subjectID, displayName)
that would represent that a user is learning a given subject. Finally, I would create a custom_subjects table of the format of
custom_subjects(id, subjectID, userID, displayName)
so, if a user has a custom displayName, then that would be used and the value would fall back to the user_subjects's displayName, a common pattern in queries would be the following:
SELECT COALESCE(custom_subjects.displayName, subjects.displayName)
FROM users
JOIN user_subjects
on users.id = user_subjects.userID
JOIN subjects
on user_subjects.subjectID = subjects.id
LEFT JOIN custom_subjects
ON subjects.id = custom_subjects.subjectID AND users.id = custom_subjects.userID
This way you will have a default to fall back to and you could override it for each user. I'm unsure about your intention about i18n, you have provided some information about that, but not enough for me to include ideas about it into my answer.

Related

SQL Display results only if the row exists in another table

Is there a way to display results only if that particular value exists, if there are multiple entries of it in another table?
For example, I am trying to display teacher name only if the type is Math. If there are no entries of Math, the column Teacher should display none.
UserName U
Email
Me
row#1.com
Wiz
bow#1.com
Classes C
Username
First
Me
Second
Me
Third
Me
Third
Wiz
Classes
Teacher T
Type
First
A
Math
Second
B
Math
Third
C
NULL
Final result as Math Classes exist for Me
UserName
Email
Teacher
Me
row#1.com
A
Me
row#1.com
B
Final result as Math Classes exist for Wiz with no math classes
UserName
Email
Teacher
Wiz
bow#1.com
None
The issue I'm running into is that my query is displaying either no entries even though user has no math but has other classes, or it's displaying Math and None at the same time.
My current query is as follows:
from User u
join classes c on c.username=u.username
join teachers t on t.classes=c.classes and type ='Math' <---- If I left join, I get 2 entries, if I join, I get 0 entries for non-math folks
where username ='Me'
So the 3 scenarios I want the query to cover:
If user does not exist in the user table (no entry)
If user exists but doesn't have any math (show user None entry)
If user exists and has math (regardless of any other type) display classes - final situation up there
Do I do some kind of select count in the case statement? This query is part of a bigger execution query.
This was SQL Server Management Studio
Would something like this solve your question?
select u.Username,
Email,
CASE WHEN types = 'MATH'
THEN teacher
ELSE 'None'
end as teacher
from users u
join class c on c.username=u.username
join teacher t on t.classes=c.classes
WHERE u.Username = 'Wiz'
db fiddle

How to make users table common for different type of users? else do i need to change User registration table based on users in laravel?

Guys iam working with an online quiz examination project.
i have a small doubt. basically user table is for registering users.
in my application iam the organization. my team has more than 5 users with different roles. I know about roles and permissions. our role is to upload questions in the db.
so lots of school will register and the staff memebers and students in the school are users of my application.
the role of staff is to create assessment by choosing the questions which is already stored in db.
after creating assessment student are requested to login and then write the exam. then results are verified.
Here my doubt is
as a oraganization iam also user here, the students and staff members of different schools also user here.
then how my user table must be changed.
this my structure
As my organization i will get
name
user_name
email
phno
password
these data are enough for my team. but when it comes to school say for example
AAA matriculation Higher Secondary school is registering to our application so i need to get the school info like school name, school address, school phno etc.
then i should register the student and staff members of that school
like
Staff A belongs to this school with this username and this password with this role with this subject ( so that when the staff login he/she can see only maths questions)
Student B belongs to this school with this username and this password with this role and this class(then only those class assessments will be shown to him/her)
so my
schoolDetails Table
id name address phno
1 School1 Address1 123
2 School2 Address2 321
3 School3 Address3 547
.
.
so on
when registering staff or student of that school
id school_id name username email password phno
1 1 A AAA a#gm ** 122
2 1 B BBB b#gm ** 789
so if i i have a user table like above then how i can register my team??
overal my doubt is how to register my team, and other school in users table
i know that i will have a class table and subject table which will be linked to user table so based on the staff or student login that changes the display screen.
My major doubt how can i register myself and them??
I would split it a bit differently.
Schools, ok
User: defines users only, without any links to schools, yet
User type: defines types that each user can have
Register: links schools and users
So if your user is strictly an administrator, and not a student, you ommit that user from the register table. This way you can even have a student take classes in two schools (if that is possible with your logic). At least is decouples schools and users (and is good for normalization anyway).
As a general rule, defines what objects you have in your requirements. Each of those become one table. Then list your relations. Single (1-1) relations become foreign keys, (many-many, 1-many) become link tables.
Tables...
Schools
ID NAME ADDRESS PHONE
1 School1 Address1 514-123-1324
2 School2 Address2 514-123-1234
...
User
ID TYPE NAME USERNAME PASSWORD PHONE
1 1 AAA usera passa 514-123-1234
2 2 BBB userb passb 514-123-1234
...
User Type
ID TYPE
1 Admin
2 Student
...
Register
ID SCHOOLID USERID
1 1 1
2 1 2
...

Multiple JOIN, with one table needed two times

i am trying to make up this situation in my app: there are users who can select the languages they speak (such as english, spanish, japanese and so on) and users who can confirm the languages selected by others users (like in LinkedIn, where you can confirm the skill of another person).
I have 4 tables in a DBRM: Users, Languages, Users_Language and Users_Confirmations.
The bodies:
Users
id name lastname ...
Languages
id name
Users_Languages
user_id language_id
Users_Confirmations
user_id language_id other_id ------> here other_id refers to Users table, like user_id. They both refer to Users table, since an user can confirm another user
For example:
John Smith speaks English, Spanish and Danish.
Luke Red and Jennifer Brown confirmed English on John Smith.
Now, I want to get all Users who, for example, have confirmed the user with id "4", and show them in a HTML list. And I would want to get it with both PURE SQL and Laravel (Eloquent or Query Builder).
Thank you in advance!
Here you have to change your table attributes to avoid repetition, use just
Users_Languages_ID as a foreign key to refer to the Users_Langages table
-- Users_Confirmations
confirmation_id user_language_id
You can just use Users_Confirmations, and for each confirmation added, you will insert a row that contains user_language_id
Returning to the question(to get users who confirmed the user with id "4")
SELECT Users.name, Users.lastname, Languages.name
FROM Users_Confirmations
JOIN Users_Languages ON Users_Languages.id = Users_Confirmations.user_language_id
JOIN Languages ON Languages.id = Users_Languages.language_id
JOIN Users ON Users.id = Users_Languages.user_id
WHERE Users_Languages.user_id = 4

What is the normalized database form for these 3 tables?

So I have three tables and subsequently three models as well:
Company (table: companies)
Person (table: people)
Address (table: addresses)
How to connect these together, considering that each Person or Company can have multiple addressess, but since the addresses are in the same format I'd like to use one single 'addresses' table, so dealing/managin addresses can be done trough a single model?
Because this structure:
companies(id, name, ...)
people(id,name, ... )
addresses(id, foreign_id, foreign_model, ...)
Seems a bit out of place for me. basically this is the current sructure now. The 'foreign_model' field is a string which specifies which model the address belongs to (i.e. Company or Person).
All this under Cakephp, but I have many problems with this structure, what should I use instead?
how abt this:
companies(id, name, address_id,..)
people (id,name, address_id,... )
addresses(id,... )
Both companies and people point to the address table for their address.
Here you dont have to store any duplicate addresses if any
EDIT: If both companies and people can have many addresses
Then keep a mapping table
companies(id, name,..)
people (id,name, ... )
addresses(id,... )
Address_map(id,address_id,type)
Where type says whether its a company or a people
id --> either companyid or poepleid

sql query with "with and in clause"

i have a table which store user name, hobby and city .hobby field contain different hobby joined using "," operator eg swimming, basket, cricket. I want to search user name who match at least one hobby according to my search criteria.
You should not have multiple attributes in one column. That's one of the number one rules of 3nf database design. Now you have to figure out ways to parse this data. This issue only gets worse and worse each and every day. Seperate the hobbies as multiple rows in your database.
I agree with #JonH that there shouldn't be more than one piece of information in a column. It stops the row being truly atomic.
But you are where you are, and you can use the LIKE clause to return rows that match a substring within a column.
Something like:
select hobbycolumn from hobbytable where hobbycolumn like '%swimming%'
for example
To do this properly you need to restructure your tables if possible. For what you are looking for a possible way would be to have 3 tables. I'm not sure who the city belongs to, so I put it with the user.
1 for user with the following cols:
id
name
city
A table for for hobbies:
id
name
And a user_hobbies join table that allows each user to have multiple hobbies, and each hobby to have multiple users:
id
user_id (foreign key)
hobby_id (foreign key)
Then searching for a user with a certain hobby is:
SELECT user.id, user.name FROM user
INNER JOIN 'user_hobbies' on user_hobbies.user_id=user.id
INNER JOIN 'hobbies' on hobbies.id = user_hobbies.hobby_id
WHERE hobbies.name LIKE "query";