When creating a many to many table, relational database. If for example you are enabling users to scrape images form around the web and tag them.
Would it be better to:
Check to see if the image is already in the database and if it is, create a link in a relational table and if it is not create a new image.
Create a unique instance of the image for every user and when looking to display the most popular images SELECT AND ORDER BY the image with the most duplicates
I hope this makes sense. Thanks in advance for you help.
I assume you have something equivalent to a USERS table and a PICTURES table. Also a table to break up the many to many relationship. U2P I will call it.
The option you listed as option 1 would seem to be the preferred way. Check to see if the picture is in the DB, if it is get primary key from PICTURES corresponding to it. If not, put the picture in the PICTURES table.
Regardless of if it is a new image, or one that is already in there, you will insert the event into the U2P table. This would reference the USERS primary key and the PICTURES primary key corresponding to the event. You would also record other data such as time etc...
Related
I have a table, where I store user uploaded files. There can be 5 different file types: profile picture, cpr file, degree file, video file, background check file.
Table structure is this:
file_id, user_id, file_type, file_size, file_name, file_new_name, file_path, file_cat, date_created
My questions:
Is this structure efficient or should I create 5 different tables?
If I would like to update, lets say user profile picture row, then what would be the best way to do it? --- I came up with a solution that probably is not be the best one- I update the row where file_cat = "profile_picture" and user_id=:user_id. Would that put a lot of load in the system?
First when user signs up, he doesn't have any files. Should I user insert into ... VALUES ... on duplicate key update with a hidden value in a form?
Thank you in advance.
This is three questions not one.
Is this structure efficient or should I create 5 different tables?
One table is good enough
If I would like to update, lets say user profile picture row, then
what would be the best way to do it? --- I came up with a solution
that probably is not be the best one- I update the row where file_cat
= "profile_picture" and user_id=:user_id. Would that put a lot of load in the system?
Not if you have an index on file_cat, user_id (composite index on both fields). If you want to make things a bit leaner you can store constants instead of 'profile_picture' etc. eg
profile_picture = 1
cpr = 2
....
background = 6
This would make the tables and indexes a bit smaller. It might make the queries slightly faster.
First when user signs up, he doesn't have any files. Should I user
insert into ... VALUES ... on duplicate key update with a hidden value
in a form?
No need for that. not having a record for new users actually makes things easier. You can do an COUNT(*) = 0 query or better still an EXISTS query without having to fetch rows and examine them.
Update:
These EXISTS queries are really usefull when you are dealing with JOINs or Sub Queries for example to quickly find if a user has uploaded a profile picc
SELECT * from users WHERE exists (SELECT * from pictures where pictures.user_id = users.id)
If you use the primary key properly then your insert ... on duplicate key update ... query will do everything for you.
For your table you need to define a primary key column. In this case I would say it is your file_id column. So if you do your insert, the MySQL server will check to see if your file_id column is defined already for that value, if so it will update with the new values, other wise it will add a new row of data with the new file_id.
I should be easy enough to separate it though, make 1 script for creating new rows and another for updating. Usually you will know when you are creating as opposed to updating in an application. Again using a primary key correctly will help you out a lot. Using a primary key in your where clause I am pretty sure is one of the most efficient ways to update.
https://dev.mysql.com/doc/refman/5.5/en/optimizing-primary-keys.html
I have a MySQL database that stores user emails and news articles that my service provides. I want users to be able to save/bookmark articles they would like to read later.
My plan for accomplishing this was to have a column, in the table where I store the users' emails, that holds comma-delineated strings of unique IDs, where the unique IDs are values assigned to each article as they are added into the database. These articles are stored in a separate table and I use UUID_SHORT() to generate the unique IDs of type BIGINT.
For example, let's say in the table where I store my articles, I have
ArticleID OtherColumn
4419350002044764160 other stuff
4419351050184556544 other stuff
In the table where I store user data, I would have
UserEmail ArticlesSaved OtherColumn
examlple1#email.com 4419350002044764160,4419351050184556544,... other stuff
examlple2#email.com 4419350002044764160,4419351050184556544,... other stuff
to indicate the first two users have saved the articles with IDs 4419350002044764160 and 4419351050184556544.
Is this a proper way to store something like this on a database? If there is a better method, could someone explain it please?
One other option I was thinking of was having a separate table for each user where I can store the IDs of the articles they saved into a column, though the answer for this post that this is not very efficient: Database efficiency - table per user vs. table of users
I would suggest one table for the user and one table his/her bookmarked articles.
USERs
id - int autoincrement
user_email - varchar50
PREFERENCES
id int autoincrement
article_index (datatype that you find accurate according to your structure)
id_user (integer)
This way it will be easy for a user to bookmark and unbookmark an article. Connecting the two tables are done with id in users and id_user in preferences. Make sure that each row in the preferences/bookmarks is one article (don't do anything comma seperated). Doing it this way will save you much time/complications - I promise!
A typical query to fetch a user's bookmarked pages would look something like this.
SELECT u.id,p.article_index,p.id_user FROM users u
LEFT JOIN preferences ON u.id=p.id_user
WHERE u.id='1' //user id goes here, make sure it's an int.. apply appropriate security to your queries.
"Proper" is a squirrely word, but the approach you suggest is pretty flawed. The resulting database no longer satisfies even first normal form, and that predicts practical problems even if you don't immediately see them. Some of the problems you would be likely to encounter are
the number of articles each user can "save" will be limited by the data type of the ArticlesSaved column;
you will have issues around duplicate "saved" article IDs; and
queries about which articles are saved will be more difficult to formulate and will probably run slower; in part because
you cannot meaningfully index the the ArticlesSaved column.
The usual way to model a many-to-many relationship (such as between users and articles) is via a separate table. In this case, such a table would have one row for each (user, saved article) pair.
Saving data in CSV format in a database field is (almost) never a good idea. You should have 3 tables :
1 table describing users with everything concerning directly the user
1 table describing articles with data about it
1 table with 2 columns "userid" and "articleid" linking both. If a user bookmarks 10 articles, this table will have 10 records with a different aticleid each time.
I'm fairly new to MySQL and PHP, but I'm getting the hang of it slowly.
I'm working on a site with profile pages. I have a users table in my database and I intend to create a profile table too.
Before I explain my 'problem' I'd like to say I haven't actually began coding an attempted solution. I like to plan my work before I start it, especially when it is going to be complex. Therefore, I can't really display any snippets of code.
What I would like to create is a tagging system for the user profiles. ie. let the profile owner select keywords from an existing list, and associate them with his profile page.
After pondering plenty and reading up on relational databases I gathered I should start by creating two additional tables:
1. tags (tag_id, tag_name)
2. tag_rel (tag_id, user_id)
and create a relationship between each profile to the different tags a user assigned to it, on seperate rows:
(Tag1, UserA)
(Tag2, UserA)
(Tag1, UserB)
etc.
Then when I search for profiles I simply have to select all user_ids with a specific tag_id. Easy enough.
My issue is the PHP and MYSQL Query code when inserting or changing the list.
I would essentially want the user to be able to either choose from a check-list or from a drop-down select list (or anything equivalent) of existing Tags, check or uncheck his selection, and send to enter it to the database.
I can imagine the initial entry of the selected tags is easy enough to achieve with a foreach() function and a simple INSERT query, and enter the array from the form one value at time.
But when the user goes back to change the tags, how would I instruct a query to keep some tags, delete others, and insert new ones in? What is the best method to do something like this?
An Idea:
Should I delete all the existing rows the user has in tag_rel, and insert the new array?
I would use a procedure like this:
at first you fetch the tags a user selected out of the db and pass them to an array (SELECT from tag_rel where user_id = $userId)
then you would go over to let the user operate on the array (adding new tags, deleting old one)
at last you would delete the old entries and insert the completely new ones from the array provided
the simplest method is to delete tag_rel data for that particular user_id then re-insert the new ones
I have an application which keeps database of all nearby restaurants.
When adding a new entry, there is an option to add a few images of your restaurant.
Now the problem:
I'd like to sort the different restaurant images into separated folders, named by restaurant id stored in mysql auto increment ID. The only problem here is, that i dont know that id in advance.
Form example:
text input - title
text input - address
text input - phone
file input - image
file input - image
So, what should I do now?
I. Get the last id, lock the table, create folder named by id, store images inside, store information to mysql database including image paths, unlock table.
or
II. Store all information excluding images paths to mysql database, use PHP mysql_insert_id, create folder named by id, store images inside and store images paths to mysql database.
or
III. Better solution?
This kind of thing is usually done with your option II. Store in the database the main row of information, get the last insert id via mysql_insert_id() or the native MySQL LAST_INSERT_ID() function, then proceed to store rows in any related tables if necessary and create the image directory to store filesystem data.
Assuming the image paths you intend to store in the database will go into a different table with a one-to-many relationship back to the main restaurant table, you'll need to know the last insert id to insert them anyway. Don't worry much about doing it in multiple operations -- that's exactly the reason most RDBMS have a function like LAST_INSERT_ID().
If you are using the autoincrement column. You can right after your insert statement call the last_insert_id() function to retrieve the id of the last inserted record.
See this link for documentation:
http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_last-insert-id
Its important that you do this within the same transaction/connection otherwise the value might be erroneous.
I don't see a need to use the restaurant's id to organize the pictures - especially since you get into the timing issues you describe. I'd create another unique id - call it picture_folder_id or something - and use that to name the folder for the pictures. As long as you enforce uniqueness on that id, you won't get any collisions, and you won't have any timing problems or locks.
Im wondering if someone could help me out with a little issue im having.
I have some code which enables a user to click a button and it will create a additional file input box ... The amount of times they can click this is unlimited, so realisticly they can add unlimited images to their profile.
The problem im having is im not sure how to go about saving that information to the database, usually i would add a row for a file input and store the name, but as there can be unlimited amounts of filenames, im not sure how i would go about saving it.
Could anyone out there give me some suggestions on how they would do it?
Thanks
I would store additional pieces of information in a separate table. It only needs 2 fields, data and user_id, Then for each additional input, you would store the data and the user's unique user_id. To retrieve the data, just filter using the user_id.
Usually it's doing using 2 tables and foreign keys. One table with users(user) (id, name, ...). Second table with photos of users(user_photo) (id, user_id, photo_path, ...). Foreign key will be created between user.id and user_photo.user_id with cascade delete/update.