having the same data values into more than one database table - sql

I have a database with 200 thousand student records, each student have an extendable profile.
Students is the Primary key table,
StudentProfiles is stores the Profiles elements:
[ProfileID],[StudentID],[PropertyDefinitionID],[PropertyValue]
Each profile contains around 120 Property, so In StudentProfiles i have 200 thousand students * 120 Profile Properties = 24 Million rows.
Some important Profile elements like Count(StudentSiblings) or GuardianEmail are used in many external operations, while the other profile elements are used rarely.
For better performance, Is there any problem if we also saved this 3 or 4 Profile Properties as columns in the master Students Table?
This is just an Example, i also have another case where i want to save the result of an aggregate function for a table in another table for easier and faster access, like storing the Sum of payments for a student in the students table as column, is that kind of Denormalization breaks the DB design standards.

If these frequently used profile elements are atomic - ie each student has only one value for GuardianEmail - then I see no reason why not to store these values in the students table, in the same way that you would store the student's email or surname in the students table.

Related

How to implement optimized Search in sql server when data is present in multiple tables with millions of rows?

In my application I need to perform searching on Employees Names,Customer Names etc. consider schema where there is an
Employees specific table EMPLOYEES ,
Customer specific table CUSTOMERS,
Core Table which contains Case Details related to an Employee
ALL these tables contain 10+million rows
now If a user enters a text in search box I am not aware of whether its customer name or Employee name etc.. now the general approach would be to search for customers in customers table, employee names in employee table and fetch those Ids and return rows with matching Ids from Core table but this would required joins of tables containing millions of rows how do I overcome this problem.
PS:
Using a FULL text search or using a HASH Table would be on my least priorities.

Storing list of strings in MySql column

I have a users table which contains data for registered users, each row represents a user. One column in particular should contain a list of groups the user is part of, at the moment that column is of TEXT type and I'm storing that list as a string where groups are separated with a semicolon, something like:
admin;moderators;devteam
And I was wondering: "Is this a good idea?", is there a better/safer way to do this that doesn't require a lot of effort to implement or is this "ok"?
Here is a pic of the table as of now:
And I was wondering: "Is this a good idea?"
Short answer: probably not.
Why
If you will ever need to do any manipulation on that column, you will find yourself in big trouble. Simply selecting all users in a group will require some operations on a string (usually not performance-friendly). Same will hold true for sorting, joining and all the other operations SQL is great for.
Solution
What you describe is a typical example of N:N relationship, where each user can belong to multiple groups and each group can have multiple users in it.
The 'standard' way of modeling this relationship is creating a new table, where each row will represent a user belonging to a group. The columns will be group and userID.
With data from your example
userID | group
--------|----------
1 | admin
1 | moderator
1 | test
This allows to have one row for each user in the users table, and getting the groups of a specific user is as simple as
select group
from user_groups
where userID = '1'

Transpose to Count columns of Boolean values on Access SQL

Ok, so I have a Student table that has 6 fields, (StudentID, HasBamboo, HasFlower, HasAloe, HasFern, HasCactus) the "HasPlant" fields are boolean, so 1 for having the plant, 0 for not having the plant.
I want to find the average number of plants that a student has. There are hundreds of students in the table. I know this could involve transposing of some sort and of course counting the boolean values and getting an average. I did look at this question SQL to transpose row pairs to columns in MS ACCESS database for information on Transposing (never done it before), but I'm thinking there would be too many columns perhaps.
My first thought was using a for loop, but I'm not sure those exist in SQL in Access. Maybe a SELECT/FROM/WHERE/IN type structure?
Just hints on the logic and some possible reading material would be greatly appreciated.
you could just get individual totals per category:
SELECT COUNT(*) FROM STUDENTS WHERE HasBamboo
add them all up, and divide by
SELECT COUNT(*) FROM STUDENTS
It's not a great database design though... Better normalized would be:
Table Students; fields StudentID, StudentName
Table Plants; fields PlantID, PlantName
Table OwnedPlants; fields StudentID,PlantID
The last table then stores records for each student that owns a particular plant; but you could easily add different information at the right place (appartment number to Students; Latin name to Plants; date aquired to OwnedPlants) without completely redesigning table structure and add lots of fields. (DatAquiredBamboo, DateAquiredFlower, etc etc)

Inserting data into a table with new and old data from another two tables

I have a table name Queue_info with structure as
Queue_Id number(10)
Movie_Id number(10)
User_Id Varchar2(20)
Status Varchar2(20)
Reserved_date date
I have two other tables named Movie_info having a many columns including movie_Id and User_info having many columns including User_Id.
In the first table movie_id, user_id is foreign key from movie_info(movie_id) and user_info(User_id).
My problem is that if I insert any value either in the Movie_info or User_info, the Queue_info table should be updated as new entry for every user or for every movie
For example
If insertion in Movie_info as new movie then queue_info should be updated as for every user the status of that new movie is awaiting.
use from triggers. by using triggers you can update all related tables to your table. for example if 1 row inserted in to table 1, 1 row insert in to table 2 too.
Some notes first:
I really like that you have a standardized way to name tables and fields. I would use Queue instead of Queue_info, Movie instead of Movie_info, etc..., as all tables have information - don't they? - and we all know that. I'd also choose MovieId instead of Movie_Id, ReservedDate instead of Resedrved_date but that's a matter of personal taste (allergy to underscores).
What I wanted to stress is that choosing one way for naming and keeping it is very good.
What I don't like is that while your structure seems normalized, you use Varchar type for the User_id Key. Primary (and Foreign) Keys are best if they are small in size and with constant size. This mainly helps in keeping index sizes small (so more efficient) and secondly because the keys are the only values stored repeatedly in the db (so it helps keeping db size small).
Now, to your question, do you really need this? I mean, you may end up having in your database thousands of movies and users. Do you want to add a thousand rows in the Queue table whenever a new movie is inserted? Or another thousand rows when a new user is registered? Or 50 thousand rows when a new list with 50 new movies arrives (and is inserted in the db)?
With 10K movies and 2K users, you'll have a 20M rows table. There is no problem with a table of that size, and one or more triggers will serve your need. What happens if you have 100K movies and 50K users though? A 5G rows table. You can deal with that too, but perhaps you can just keep in that table only the movies that a user is interested in (or has borrowed or has seen, whatever the purpose of the db is). And if you want to have a list of movies that a certain user has not yet been interested in, check for those Movie_Id that do not exist in the table. with something like this:
SELECT
Movie_Id, Movie_Title
FROM
Movie_info AS m
WHERE
NOT EXISTS
( SELECT *
FROM Queue_info AS q
WHERE q.Movie_Id = m.Movie_Id
AND q.User_Id = #UserId
)

How to display multiple values in a MySQL database?

I was wondering how can you display multiple values in a database for example, lets say you have a user who will fill out a form that asks them to type in what types of foods they like for example cookies, candy, apples, bread and so on.
How can I store it in the MySQL database under the same field called food?
How will the field food structure look like?
You may want to read the excellent Wikipedia article on database normalization.
You don't want to store multiple values in a single field. You want to do something like this:
form_responses
id
[whatever other fields your form has]
foods_liked
form_response_id
food_name
Where form_responses is the table containing things that are singular (like a person's name or address, or something where there aren't multiple values). foods_liked.form_response_id is a reference to the form_responses table, so the foods liked by the person who has response number six will have a value of six for the form_response_id field in foods_liked. You'll have one row in that table for each food liked by the person.
Edit: Others have suggested a three-table structure, which is certainly better if you are limiting your users to selecting foods from a predefined list. The three-table structure may be better in the case that you are allowing them the ability to enter their own foods, though if you go that route you'll want to be careful to normalize your input (trim whitespace, fix capitalization, etc.) so you don't end up with duplicate entries in that table.
normally, we do NOT work out like this. try to use a relation table.
Table 1: tbl_food
ID primary key, auto increment
FNAME varchar
Table 2: tbl_user
ID primary key, auto increment
USER varchar
Table 3: tbl_userfood
RID auto increment
USERID int
FOODID int
Use similar format to store your data, instead a chunk of data fitted into a field.
Querying in these tables are easier than parsing the chunk of data too.
Use normalization.
More specifically, create a table called users. Create another called foods. Then link the two tables together with a many-to-many table called users_to_foods referencing each others foreign keys.
One way to do it would be to serialize the food data in your programming language, and then store it in the food field. This would then allow you to query the database, get the serialized food data, and convert it back into a native data structure (probably an array in this case) in your programming language.
The problem with this approach is that you will be storing a lot of the same data over and over, e.g. if a lot of people like cookies, the string "cookies" will be stored over and over. Another problem is searching for everyone who likes one particular food. To do that, you would have to select the food data for each record, unserialize it, and see if the selected food is contained within. This is a very inefficient.
Instead you'll want to create 3 tables: a users table, a foods table, and a join table. The users and foods tables will contain one record for each user and food respectively. The join table will have two fields: user_id and food_id. For every food a user chooses as a favorite, it adds a record to the join table of the user's ID and the food ID.
As an example, to pull all the users who like a particular food with id FOOD_ID, your query would be:
SELECT users.id, users.name
FROM users, join_table
WHERE join_table.food_id = FOOD_ID
AND join_table.user_id = users.id;