Say I have a database with 3 tables: Stream, Tag and Post
Stream has one tag. Multiple streams can have the same tag.
Stream is owned by one user.
A tag has many posts.
Different tags can have the same post.
Each user that opens his stream gets it's posts (via the tag) and can delete (or hide) the posts he doesn't want to see (but only for him, not for others).
What would be the appropriate way to achieve this? Obviously I'll need some kind of soft-delete flag on posts. I currently have 2 ideas in mind:
Create another table that will act as the view of the stream with columns stream_id, post_id and is_deleted
Add deleted column to Stream that holds a JSON array of deleted posts' ids. The problem with this approach is querying based on is_deleted state.
Are there any better ways?
Note: Currently, I need Tag to stay in it's own table, rather than storing it as text in a column in Stream
You should have a new table with the columns post_id, is_deleted & user_id.
In this way you can manage it easily or else it will be hectic work as per your options are considered.
The table name will be like cross reference table ex: user_deleted_posts_xref
Related
I have an assignment where I need make a table for users which houses basic information like fname,lname,email...etc but I also need to store information about the users location address,zip,city,state...etc. A user can have multiple location information.
I've been just doing a csv but people are telling its pretty bad to do that so I'm trying to do things the right way.
I was learning about many to many and it seems to do the trick. But the problem is I need to load this data to a table for viewing.
I just don't see anyway that this would work without having to do a query inside the first query.
ie:
while($row=mysqli_fetch_assoc($query)){
$id = $row['id'];
///Get user locations based on id here.
}
From what I understand if we're storing user ID lets say to a table to make the relation to the locations table and a user can have multiple locations would join be useless here?
I need to pull up records 25 at a time so it's not only supposed to pull one. I'm using datatables with the collapse/show so the data needs to be in a separate container
The Approach of storing location separately in other table with user_id column will be good and as the user will be unique let's say he is unique regarding his email, his locations can be fetched.
Other approach, You can store locations(multiple) in form of object and fetch them then you can get individual location by decoding the json
I have 200 users each user will eventually have a "reviewINFO" table with certain data.
Each user will have a review every 3 to 4 months
So for every review, it creates a new row inside the "reviewINFO" table.
This is where i'm stuck. I'm not sure if I need to serialize a table inside each row or not.
Example:
-> links
"USER1reviewINFO"-row1->USER1table1
-row2->USER1table2
-row3->USER1table3
-row4->USER1table4
-row5->USER1table5
"USER2reviewINFO"-row1->USER2table1
-row2->USER2table2
-row3->USER2table3
-row4->USER2table4
-row5->USER2table5
using this method it will make a couple of thousand rows within two years. And I think its harder to manage.
"Userxtablex" is a table with dynamic rows of children names,ages,boolean
What i'm think of doing is serialize each USERxtable into its corresponding row.
Please help as I would not like to make this complicate or inefficient
Generally, you should never have to serialize data of this nature into a table row to accomplish what your goal is (which I am assuming is an implicit link between a user and a review)
What you need to do is key the reviews by a user_id such that all the reviews are packaged in one table, and relate numerically back to the users table.
Assuming you have an AUTO_INCREMENT primary key in the user table, all you would need is a user_id field in the reviews table that represents what user the review relates to. There is no need for a separate structure for each user, if that's what you are suggesting. Reviews can have date fields as well, so you can perform queries for a specific year or window of time.
You can then use a JOIN query to select out your data set relating to a particular user or review, and apply the usual WHERE clause to determine what result set you want to fetch.
----- PHP and mySQL -----
I have two quick questions need some advice.
On my site I will allow users to upload following files - PDF/Videos/Photos. All files uploaded by the user are shown on a profile page. All uploaded files can be searched by name or tags and file type.
What would be the best mysql database design?
Store all files in one table, easier to display on user’s profile page and searching by type and etc.
One table per type e.g. pdf, videos and photos <- this might be better for performance but for searching I don’t know?
Second question is, I allow users to create their own menus/categories with parent and children categories for example:
->parent category
> child category
> child category
->parent category
> child category
> child category
At moment I have two database tables, one stores all the parent categories for each user and second store child category with foreign key (id) to parent category.
To get all the categories I first get all the parent categories and using a foreach loop.
I call a function within the loop to get the children categories by parent id.
I want to know is this the best approach of doing this or can this be done in mySQL query without looping?
thanks guys !!!
For your first question, it depends on what information you want to store about the files.
If it's generic across all types, (name, date, filetype, size, etc.) then a single Files table by itself with a type column makes sense.
But if you're going to save attributes of the files that have to do with what kind of file they are, frame rate of a video file, height and width of an image file, author of a PDF, for example, then you will also need some ancillary tables to store that information. You don't want to have a bunch of columns hanging off your file table that are only useful each for a certain file type.
For your second question, the rough SQL is based on a JOIN between your parent category table and your child category tables.
Example psuedo code:
select p.userid, p.parentcategoryid,c.childcategoryid
from ParentCategory p INNER JOIN
ChildCategory c
on p.parentcategoryid=c.parentcategoryid
WHERE
p.userid = #UserID
The website I'm building has a table which stores all the information of uploaded images on the site. These uploaded images can come from different resources such as a guestbook, news section or an item from an agenda.
Ofcourse I want the image to inherit the rights of the resource it is part of. For example: if user A isn't allowed to view the guestbook I don't want him to be able to view an image posted on the guestbook by going to image/view/id/12 (which would be the image request used it in the guestbook).
What I have now is that the system remembers the resources used (in this case the guestbook) the image-id is coupled to the resource-id. However I don't know to which guestbook post the image is connected (I do ofcourse know it the other way around).
Is there a way in SQL to connect one table field to a field in another table, where which table I connect to can vary based on one of the first table's field values?
In my case I would like to connect an image to a resource this could be a guestbook post in the table gb_posts or an agenda item in the table agenda_items.
Or is this all a stupid way of solving the problem and should I not use one table for the uploaded images but keep the image attached to the resource (as a column in the table for example)? It sounds like using one table is at least a lot slower in use (but I would have a great overview of all the images in one place).
I hope you guys can help me out.
EDIT: extra explanation: db model
I will try to explain how it all works the best I can.
First of all: I use Zend Framework, and therefor I also use Zend_Acl for working with priveleges.
My DB structure:
- Users are connected to roles (directly or by being connected to a group that is connected to a role)
- There is a table resources containing all the resources which is connected to priveleges. For example: guestbook is a resource, view or edit are the priveleges. Next to the controllers/actions there can also be other resources in this table such as a category within the agenda or a file location.
- roles are connected to a privelege
When for example the guestbook is requested for viewing I can check if the user is allowed to.
In short something like:
users -> roles -> priveleges <- resources
When a user adds a guestbook post with an image, the used resources (in this case guestbook is saved):
guestbook_posts -> images -> resources
I hope this explains my DB model for a bit, if it doesn't I will try to create an image of the tables.
I have to admit I'm failing to completely understand the model you wish to implement, but there is an interesting quote...
However I don't know to which
guestbook post the image is connected
(I do ofcourse know it the other way
around).
If you know an association one way, you should be able to use the associaton in both directions? I'm assuming you have a table that includes "post_id, image_id", or something?
It may be that the table is only indexed post_id first, in which case querying that table by image_id may be slow, but then you can just include a new index with image_id first?
If you can give examples of the table structure you have at present, and an example of the query you can't fullfil, we may be able to help you further.
Sounds like you want a foreign key constraint.
Update: Completely misunderstood the question, apparently.
There are two approaches here:
As it currently stands, there is nothing in the schema that would prohibit linking the same image from multiple resources. If that is desired, then a foreign key constraint and an index for the backreference is probably the best solution, although it will not scale well, and requires additional computation (because the rights on the image need to be the union of the rights of the refering resources).
The alternative is to create some kind of inheritance schema, where there is a table listing "resources" (that effectively just contains identifiers) that is referenced as a foreign key from the actual resource tables and the images table; the only constraint that cannot be expressed in plain SQL is that different resources may not share the same identifier.
Create two SELECT clauses, each having the correct joins to the correct tables, and then combine the output of the two SELECT clauses together using a UNION statement.
SELECT field1, field2
FROM table1
JOIN table2 on table1.PK = table2.FK
WHERE table1.selector = 1
UNION SELECT field1, field2
FROM table1
JOIN table3 on table1.PK = table3.FK
WHERE table1.selector = 2
I need to save a list of user ids who viewed a page, streamed a song and / or downloaded it. What I do with the list is add to it and show it. I don't really need to save more info than that, and I came up with two solutions. Which one is better, or is there an even better solution I missed:
The KISS solution - 1 table with the primary key the song id and a text field for each of the three interactions above (view, download, stream) in which there will be a comma separated list of user ids. Adding to it will be just a concatenation operation.
The "best practice" solution - Have 3 tables with the primary key the song id and a field of user id that did the interaction. Each row has one user id and I could add stuff like date and other stuff.
One thing that makes me lean towards options 2 is that it may be easier to check whether the user has already voted on a song?
tl;dr version - Is it better to use a text field to save arrays as comma separated values, or have each item in the array in a separate table row.
Definitely the 2nd:
You'll be able to scale your application as it grows
It will be less programming language dependent
You'll be able to make queries faster and cleaner
It will be less painful for any other programmer coding / debugging your application later
Additionally, I'd add a new table called "operations" with their ID, so you can add different operations if you need later, storing the operation ID instead of a string on each row ("view", "download", "stream").
It's definitely better to have each item in a separate row. Manipulating text fields has performance disadvantages by itself. But if ever you want to find out which songs user 1234 has viewed/listened to/etc., you'd have to do something like
SELECT * FROM songactions WHERE userlist LIKE '%,1234,%' OR userlist LIKE '1234,%' OR userlist LIKE '%,1234' OR userlist='1234';
It'd be just horribly, horribly painful.