Database design for chatroom application - mysql

EDIT
People think this question is too broad so I'm narrowing things down a bit here:
I have a table with dual primary keys: roomID and userID.
Here is some example data:
roomID | userID
1 | 5
1 | 9
1 | 10
1 | 12
2 | 5
2 | 9
2 | 10
3 | 5
3 | 17
Given a list of users: 5,9,10, how can I return the roomID containing ONLY those users? So in this case it should return 2.
I hope this can be done within 1 SQL query.
Any help would be appreicated.
ORIGINAL QUESTION
I am making a chat room application and need to design a database backend for it. All the rooms are created on the fly and are destroyed when the last user exits the room. Users are able to add other users to any room they are in.
Currently this is my design:
I have a chatroom table with two columns. The two columns are both primary keys for the table (so a row is considered duplicate only when both columns are the same). The first column is the room ID. The second column is a user ID. The idea I have here is with the same room ID, there can be many users in this room (so rows with same room ID but different user ID). When I need to create a new room, I simply select MAX(room ID) + 1 and create a new room with this ID and add the users into it.
Given a list of users IDs (such as 1,5,31,12), I need to find out if a room is already created for them. In other words, I need to determine if there are rows all with the same room ID having users IDs 1,5,31,12. However, if a room is created with users 1,5,31,12,6 (one or more extra users), this should not count as room already created. I will then need to create a new room for them and add the users to that. Same goes for less users than the list.
Right now I'm having trouble forming the query to determine if I need to create a new room or not, and if not, retrieve the room ID of the existing room.
Any help would be appreciated.
Also, I think this design is quite cumbersome, you are welcome to suggest a better database design.
P.S. the database I'm using is MySQL

I think yoy can add 1 more col to the chatroom table, name num_member, this is number of member in room( or better have room(room_id, number_member) table). To make it simple first, I assume you have num_member in chatroom. This query might work:
Select * From chatroom where user_id IN ($userIdList) Group by room_id HAVING count(*) = chatroom.num_member
Hope this help

Related

Checking users who have only one activity on a job in Mysql

I have a table called activities.
The Admin gives users Some job With unique code to do.
when a user doing something on one of his jobs. user add one record on table with
unique code job and user_id.
I want to count the number of jobs the user has just done an activity on that.
I want to show something like this :
user_id | Count Jobs with one activity
1 | 5
2 | 7
.....
in this case user with id 1 has 5 jobs that he just do one activity on it.
* one job is blong to one user and another user can not do activity on it.
I'm sorry if my english is not good
there is a sample of activities table :
Here you go.
SELECT user_id, count(*) as Job_counts
FROM activity_table
GROUP BY user_id;

Select all values from one table, check another table to see related columns and fetch more values

I really dont know how to phrase my question, probably why google is not giving me results that i need, but am going to try.
I have two tables, required_files table and submitted_files table. I have a page where i want to display to a user all required files for submission and show which files he/she has submitted.
Required files table is as follows:
file_id file_name mandatory
1 Registration Certificate 0
2 KRA Clearance 1
3 3 Months Tax returns 0
4 Business Permit 1
5 Tour Permit 1
6 Country Govt Operating License 0
7 Certificate of good Conduct 0
file_id is unique, mandatory column is binary value to state whether the file is mandatory before registration or not.
submitted files table is a follows
file_id user_id file_required_id original_file_name file_name_on_server submission_date
1 2 2 KRA_Form.docx 0a10f5291e9bcb6a345ac7a8f5705b8a.docx 2016-11-01
2 2 3 Tax_returns.docx 9f04361013df7e25235a03c506f347ed.docx 2016-11-03
3 3 3 Taxes.docx 86aea74cc87fb669510d9d4c488cbcf8.docx 2016-11-04
file_id is unique AI value, user_id col is unique value of the current user logged in, file_required_id column is related to files_required.file_id column
When fetching the values i already have a user_id (in this case, lets use user_id = 2) Now i want to fetch all values of files_required table and check on files submitted table for files that user_id = 2 meaning user has submitted the files.
my sql query is as follows
SELECT files_required.*, submitted_files.* FROM submitted_files
RIGHT JOIN files_required ON files_required.id = submitted_files.file_required_id
WHERE submitted_files.user_id = 2
This gives me two rows only where the user_ids matched but i want the entire files_required table values and show which files the user has submitted. Someone Kindly assist.
In the meantime, i am fetching files_requied table first then looping through the other table using a php script to look for submitted files for the given user. it works but its not what i wanted and is cumbersome and a rookie move.
Try having user_id condition in RIGHT JOIN itself like below query
SELECT files_required.*, submitted_files.*
FROM submitted_files
RIGHT JOIN files_required ON files_required.id = submitted_files.file_required_id
AND submitted_files.user_id = 2
You want this.
SELECT submitted_files.user_id, files_required.*, submitted_files.*
FROM submitted_files
RIGHT JOIN files_required ON files_required.id =
submitted_files.file_required_id
Don't put the where condition on userid as it will filter out the data just for that user. You want all the records and user should also be seen. Just put the user_id in the select statement.

What table structure would best fit this scenario?

I am developing an evaluation system for different programs that needs a lot of flexibility. Each program will have different things to track, so I need to store what data points they want to track, and the corresponding data for the person being evaluated on the particular data point. I am guessing several tables are appropriate. Here is a general outline:
Table: accounts
- unique ID assigned to each account. We'll call this 'aid'
Table: users
- each user with unique ID.
Table: evaluation
- each program will enter in the metrics they want to track into this table (i.e attendance)
- column 'aid' will correspond to 'aid' in account table
Table: evaluation_data
- data (i.e attendance) entered into this database
- column 'aid' will correspond to 'aid' in account table
- column 'uid' will correspond to 'uid' in user table
The input form for evaluation_data will be generated from what's in the evaluation table.
This is the only logical way I can think of doing this. Some of these tables will be growing quite large over time. Is this the most optimal way of doing this?
I'm a little confused about how accounts, users and programs all relate to each other and whether or not account and program are the same thing and that you used the terms interchangeably. I'm going to use different terms which are just easier for me to understand.
Say you have a website that allows freelancers to keep track of different projects and they can create their own data to track. (Hope you see the similarity)
Tables...
freelancers
id title etc
projects
id freelancer_id title description etc
data_options
id freelancer_id title
You can even add other columns like data_type and give options like URL, email, text, date, etc which can be used for validation or to help format the input form.
example data:
1 5 Status
2 5 Budget
3 5 Customer
4 99 Job Type
5 99 Deadline
6 102 Price
7 102 Status
8 102 Due By
This display 3 different freelancers tracking data, freelancers with the id's 5, 99, and 102. Deadline and Due By are essentially the same but freelancers can call these whatever they want.
data_values
id project_id option_id option_value
a column freelancer_id as you would be able to to a join and get the freelancer_id from either the project_id or the option_id
example data:
1000 1 2 $250
1001 1 1 Completed
1002 1 3 Martha Hayes
This is only showing information freelancer with the id 5 has input because option_id's 1-3 belong to that user.

ORDER BY proirity with specific value

I have a table with a column named role and values are as follow:
Scientific staff
PostDocs
Supporting staff
PNUT
Visiting researchers
Secretary
Ph.D. students
Students
Other
I want to use ORDER BY in such a way that Scientific staff comes first. At the moment when I do a query like this, the fields which are Ph.D. students will be returned first (Well because at the moment no row in database has a field with Other in it). Is there a way to achive this using mysql only or should I modify the returned values manually? If so, can you please tell me how?
SELECT * FROM members ORDER BY role
You can do it without an additional table and join, just do:
SELECT * FROM members
ORDER BY
CASE role
WHEN 'Scientific staff' THEN 1
WHEN 'PostDocs' THEN 2
WHEN 'Supporting staff' THEN 5
WHEN 'PNUT' THEN 6
WHEN 'Visiting researchers' THEN 4
WHEN 'Secretary' THEN 3
WHEN 'Ph.D. students' THEN 8
WHEN 'Students' THEN 7
WHEN 'Other' THEN 9
ELSE 10
END
As it is currently implemented, you cannot order by in such a way that Scientific Staff is first, because doing an Oder By sorts it in order of the item in question (in your case, alphabetically it appears by role).
Now, the easy solution to this is to build out a sort priority table with those values in it, assign a numeric priority, then sort by the priority. Let me explain that a little better because it can be confusing:
You make a second table, listing each of these roles, and in a second column give those roles a priority that they will be displayed by.
TABLE:
Role | Priority
Scientific Staff | 1
Ph.D Students | 2
Other | 3
(etc)
You can then do something like this (pseudo-MySQL):
select members.role from members
inner join priority
on members.role = priority.role
order by priority.priority
that will give you the role field from the members table, ordered by the priority you set on the priority table. Since it is an inner join, anyone without a role will not display.

MySQL: How to pull information from multiple tables based on information in other tables?

Ok, I have 5 tables which I need to pull information from based on one variable.
gameinfo
id | name | platforminfoid
gamerinfo
id | name | contact | tag
platforminfo
id | name | abbreviation
rosterinfo
id | name | gameinfoid
rosters
id | gamerinfoid | rosterinfoid
The 1 variable would be gamerinfo.id, which would then pull all relevant data from gamerinfo, which would pull all relevant data from rosters, which would pull all relevant data from rosterinfo, which would pull all relevant data from gameinfo, which would then pull all relevant data from platforminfo.
Basically it breaks down like this:
gamerinfo contains the gamers basic
information.
rosterinfo contains basic information about the rosters
(ie name and the game the roster is
aimed towards)
rosters contains the actual link from the gamer to the
different rosters (gamers can be on
multiple rosters)
gameinfo contains basic information about the games (ie
name and platform)
platform info contains information about the
different platforms the games are
played on (it is possible for a game
to be played on multiple platforms)
I am pretty new to SQL queries involving JOINs and UNIONs and such, usually I would just break it up into multiple queries but I thought there has to be a better way, so after looking around the net, I couldn't find (or maybe I just couldn't understand what I was looking at) what I was looking for. If anyone can point me in the right direction I would be most grateful.
There is nothing wrong with querying the required data step-by-step. If you use JOINs in your SQL over 5 tables, we sure to have useful indexes on all important columns. Also, this could create a lot of duplicate data:
Imagine this: You need 1 record from gamerinfo, maybe 3 of gameinfo, 4 ouf of rosters and both 3 out of the remaining two tables. This would give you a result of 1*3*4*3*3 = 108 records, which will look like this:
ID Col2 Col3
1 1 1
1 1 2
1 1 3
1 2 1
... ... ...
You can see that you would fetch the ID 108 times, even if you only need it once. So my advice would be to stick with mostly single, simple queries to get the data you need.
There is no need for UNION just multiple JOINs should do the work
SELECT gameinfo.id AS g_id, gameinfo.name AS g_name, platforminfoid.name AS p_name, platforminfoid.abbreviation AS p_abb, rosterinfo.name AS r_name
FROM gameinfo
LEFT JOIN platforminfo ON gameinfo.platforminfoid = platforminfo.id
LEFT JOIN rosters ON rosters.gameinfoid = gameinfo.id
LEFT JOIN rosterinfo ON rosterinfo.id = rosters.rosterinfoid
WHERE gameinfo.id = XXXX
this should pull all info about game based on game id
indexing on all id(s) gameinfoid, platformid, rosterinfoid will help on performance