I am currently making a database, and truth to be told I'm not exactly very good at it (kinda being forced to do it). Its a game database, and I have a table called game_table that I use for storing game sessions that users create.
The question is, what is the best way to store a list of invited users, requested users, confirmed users, declined users and pending users? Currently I am serializing the user IDs (e.g. invited users = "11235|2510|34630|45715|64530"). However, the main problem is that the field becomes not searchable, and it becomes a problem if I want to retrieve a list of games that a user is invited to. To solve that problem, I store a separate field in the user_table for invited_games (also serialized game IDs).
The problem with that, is that it is getting hard to maintain whenever I want to add new features, and it is too easy to make mistakes with keeping the serialized data in sync. Is it better to have separate tables like:
invited_users_table
Game_ID | User_ID
51 | 5193
51 | 10458
51 | 235
901 | 1536
901 | 4573
Or is there some other better way of storing these types of data? Please help, and thanks!
From what you say, it sounds like you need one table with three columns:
GameId
UserId
UserType
The latter would take on values such as "invited", "confirmed", "requested" and so on.
You would want separate tables if you had more information about the different groups. For instance, you might have a "who invited" column for invited users, or a "confirmation time" for confirmed users. If the number of specific columns needed for the different groups is large-ish, then you might want to think about a more complex data structure. If there are just a handful of such columns, you can add them into the table described above.
Yes, it is better to have a separate table for invited users.
Yet better would be to have game_user_relation table, which will store the game id, the user id and the relationship between them. Kinda:
create table game_user_relation(
game_id int not null,
user_id int not null,
relation_type varchar (10) not null,
primary key(game_id, user_id, relation_type)
) engine=InnoDB;
This table will allow one user to have many relations to one game.
Or, if you need to have exactly one user relate to one game - remove relation_type from primary key.
This way you could select all needed data from one table.
Related
i have 1 table in phpmyadmin users which contains below fields.
users:
uid | name | contact.no
There can be more then one contact number for a single user.
One way to solve it is using one more table for contact number and pass its primary key to users table.
Is there any other way other then this one.
Can we implement array structure in contact.no field?
You could put commas over there and save multiple numbers but then it kills the whole concept of an RDMS and Normalization. That will not be a good database design. So it is advisable to normalize your table and not store such multiple information in one field. Database doesn't really stress itself if you have 1 more table.
A very well written explanation can be found Here on Microsoft Website
You wouldn't have to create multiple tables for each type of entry, just a more robust table structure. Make sure that the information that needs to be normalized is in a consistent format.
Users:
uid | name | username
1,Bob,bcratchet
Info:
iid | itype | icontent | uid
1,cell,000.000.0000
2,home,000.000.0000
3,home_addr,1234 Anystreet, anytown USA
4,work_addr,4567 Anystreet, anytown USA
select * from Users u,Info i where u.uid=i.uid and name="Bob";
Pull it into a multidimensional array in any application and you're good to go.
edit*
Ideally it would go further and show a table like itypes where you would further normalize the types like so:
itypes: itype_id | itype
1,cell
2,home
3,home_addr
4,work_addr
Then in the Info table it would say "itype_id" instead of "itype."
There are four regions with more than one million records total. Should I create a table with a region column or a table for each region and combine them to get the top ranks?
If I combine all four regions, none of my columns will be unique so I will need to also add an id column for my primary key. Otherwise, name, accountId & characterId would be candidate keys or should I just add an id column anyways.
Table:
----------------------------------------------------------------
| name | accountId | iconId | level | characterId | updateDate |
----------------------------------------------------------------
Edit:
Should I look into partitioning the table by region_id?
Because all records are related to a particular region, a single database table in 3NF(e.g All-Regions) containing a regionId along with other attributes should work.
The correct answer, as usually with database design, is "It depends".
First of all, (IMHO) a good primary key should belong to the database, not to the users :)
So, if accountId and characterId are user-editable or prominently displayed to the user, they should not be used for the primary key of the table(s) anyway. And using name (or any other user-generated string) for a key is just asking for trouble.
As for the regions, try to divine how the records will be used.
Whether most of the queries will use only a single region, or most of them will use data across regions?
Is there a possibility that the schemas for different regions might diverge?
Will there be different usage scenarios for similar data? (e.g. different phone number patterns for different regions)
Bottom line, both approaches will work, let your data tell you which approach will be more manageable.
I need to sell items on my fictitious website and as such have come up with a couple of tables and was wondering if anyone could let me know if this is plausible and if not where i might be able to change things?
I am thinking along the lines of;
Products table : ID, Name, Cost, mediaType(FK)
Media: Id, Name(book, cd, dvd etc)
What is confusing me is that a user might have / own many products, but how would you store an array of product id's in a single column?
Thanks
You could something like store a JSON array in a text or varchar field and let the application handle parsing it.
MySQL doesn't have a native array type, unlike say PostgreSQL, but in general I find if you're trying to store an array you're probably doing something wrong. Of course every rule has its exceptions.
What your probably want is a user table and then a table that correlates products to users. If a product is only going to relate to one user then you can add a user ID column to your Products table. If not, then you'll want another lookup table which handles the many to many relationship. It would look something like this:
------------------------
| user_id | product_id |
------------------------
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 2 | 2 |
| 3 | 1 |
| 3 | 5 |
------------------------
I think one way of storing all the products which user has in one column is to store it as a string where product ids are separated by some delimiters like comma. Though this is not the way you want to solve. The best way to solve this problem would be to have a seperate user table and than have a user product table where you associate userid with product id. You could than simple use a simple query to get list of all the products owned by a particular userid
As a starting point, try to think of the system in terms of the major parts - you would have a 'warehouse', so you need a table to list the products you have, and you are going to possibly have users who register their details with you for regular visits - so an account per user. You would generally hold all details of a single product in the same row of the same table (unless you have a really complex product to detail, but not likely). If you're going to keep track of products bought per user account, there's always the option of keeping the order history as a delimited list in a large text field. For example: date,id,id,id,id;date,id,id. Or you could simply refer to order numbers and have a separate table for orders placed [by any customer].
What is confusing me is that a user might have / own many products, but how would you store an array of product id's in a single column?
This is called a "many-to-many" relationship. In essence you would have a table for users, a table for products, and a table to map them like this:
[table] Users
- id
- name
[table] Products
- id
- name
- price
[table] Users_Products
- user_id
- product_id
Then when you want to know what products a user has, you could perform a query like:
SELECT product_id FROM Users_Products WHERE user_id=23;
Of course, user id 23 is fictituous for examples sake. The resulting recordset would contain the id's of all the products the user owns.
You wouldn't store an array of things into a single column. In fact you usually wouldn't store them in separate columns either.
You need to step away from design for a bit and go investigate third normal form. That should be you starting point and, in the vast majority of cases, your ending point for designing database schemas.
The correct way of handling variable size "arrays" is with two tables with a many to one relationship, something like:
Users
User ID (primary key)
Name
Other user info
Objects:
Object Id (primary key)
User id (foreign key, references Users(User id)
Other object info
That's the simplest form where one object is tied to a specific user, but a specific user may have any number of objects.
Where an object can be "owned" by multiple users (I say an object meaning (for example) the book "Death of a Salesman", but obviously each user has their own copy of an object), you use a joining table:
Users
User ID (primary key)
Name
Other user info
Objects:
Object Id (primary key)
User id (foreign key, references Users(User id))
Other object info
UserObjects:
User id (foreign key, references Users(User id))
Object id (foreign key, references Objects(Object id))
Count
primary key (User id, Object id)
Similarly, you can handle one or more by adding an object id to the Users table.
But, until you've nutted out the simplest form and understand 3NF, they won't generally matter to you.
I'm creating a new DB and I have this problem: I have two type of users that can place orders: registered users (that is, they have a login) and guest users (that is, no login). The data for registered users and guest users are different and that's why I'm thinking of using two different tables, but the orders (that share the same workflow) are all the same, so I'm thinking about using only one table.
I've read here and here (even if I don't understand fully this example) that I can enforce a MySQL rule to have mutually exclusive columns in a table (in my case they'd be "idGuest" and "idUser") but I don't like that approach.
Is there a better way to do it?
There are several approaches, which depends on the number of records and number of unique fields. For example, if you would say they differ in only two fields, I would have suggested that you just put everything in the same table.
My approach, assuming they differ a lot, would be to think "objects":
You have a main user table, and for each user type you have another table that "elaborates" that user info.
Users
-----
id,email,phone,user_type(guest or registered)
reg_users
---------
users_id, username,password etc.....
unreg_users
-----------
user_id,last_known_address, favorite_color....etc
Where user_id is foreign key to users table
Sounds like mostly a relational supertype/subtype issue. I've answered a similar question and included sample code that you should be able to adapt without much trouble. (Make sure you read the comments.)
The mildly complicating factor for you is that one subtype (guest users) could someday become a different subtype (registered users). How you'd handle that would be application-dependent. (Meaning you'd know, but probably nobody else would.)
I think I would have three tables :
A user table, that would contain :
One row for each user, no matter what type of user
The data that's present for both guests and registered
A field that indicates if a row corresponds to a registered or a guest
A guest table, that would contain :
One row per guest user,
The data that's specific to guests
And a registered table, that would contain :
One row per registered user,
The data that's specific to registered users
Then, when referencing a user (in your orders table, for example), you'd always use the id of the user table.
What you are describing is a polymorphic table. It sounds scary, but it really isn't so bad.
You can keep your separate User and Guest tables. For your Orders table, you have two columns: foreign_id and foreign_type (you can name them anything). The foreign_id is the id of the User or Guest in your case, and the content of the foreign_type is going to be either user or guest:
id | foreign_id | foreign_type | other_data
-------------------------------------------------
1 | 1 | user | ...
2 | 1 | guest | ...
To select rows for a particular user or guest, just specify the foreign_type along with the ID:
SELECT * FROM orders WHERE foreign_id = 1 AND foreign_type = 'guest';
The foreign key in the Orders table pointing back to the Customer entity that placed the order is typically a non-nullable column. If you have two different Customer tables (RegisteredCustomer and GuestCustomer) then you would requiree two separate nullable columns in the Orders table pointing back to the separate customer tables. What I would suggest is to have only one Customers table, containing only those rows (EDIT: sorry, meant to write only those COLUMNS) that are common to registered users and guest users, and then a RegisteredUsers table which has a foreign-key relationship with the Customers table.
Newish to mysql DBs here. I have a table of USERS and a table of TEAMS. A user can be on more then one team. What's the best way to store the relationship between a user and what teams he's on?
Lets say there are hundreds of teams, each team consists of about 20 users, and on average a user could be on about 10 teams, also note that users can change teams from time to time.
I can think of possibly adding a column to my TEAMS table which holds a list of user ids, but then i'd have to add a column to my USERS table which holds a list of team ids. Although this might be a solution it seems messy for updating membership. It seems like there might be a smarter way to handle this information... Like another table perhaps? Thoughts?
Thanks!
ps, whats the best field type for storing a list, and whats the best way to delimit?
whats the best field type for storing a list, and whats the best way to delimit?
It's usually a really bad idea to try to store multiple values in a single column. It's hell to process and you'll never get proper referential integrity.
What you're really looking for is a join table. For example:
CREATE TABLE user_teams (
user_id INT NOT NULL FOREIGN KEY REFERENCES users(id),
team_id INT NOT NULL FOREIGN KEY REFERENCES teams(id),
PRIMARY KEY (user_id, team_id)
);
so there can be any number of team_ids for one user and any number of user_ids for one team. (But the primary key ensures there aren't duplicate mappings of the same user-and-team.)
Then to select team details for a user you could say something like:
SELECT teams.*
FROM user_teams
JOIN teams ON teams.id= user_teams.team_id
WHERE user_teams.user_id= (...some id...);