Table with user activities - design issue - sql

On my site user can make some items and those items goes in Items table.
Users can also follow each other and those data I store in Followings table.
Now I need one table that keep track of user activities, so I have created:
Users{UserId, Username, FirstName, LastName}
Items{ItemId, Title, CreatedByUserId}
Activity{ActivityId, ActivityTypeId, UserId, ItemId}
Here ItemId can be or ItemId from Items table or UserId from Users table.
Is this design good or there is better approach to do this?
Edit: I have added table structures. The point is that I wan't to add record to that Activity table every time when user create item or start to follow some user. So I can always track what user did on the site.

Here ItemId can be or ItemId from Items table or UserId from Users table.
This will prevent the DBMS from enforcing the foreign key. If you go down that route, better separate these fields (so you can make foreign keys towards their respective tables) and use a CHECK to ensure exactly one of them is non-NULL:
CHECK (
(ITEM_ID IS NOT NULL AND FOLLOWED_USER_ID IS NULL)
OR (ITEM_ID IS NULL AND FOLLOWED_USER_ID IS NOT NULL)
)
The ACTIVITY PK is crafted so it is easy to query for a "timeline" of a specific user and is friendly to clustering.
(You may or may not need ACTIVITY.TYPE depending on what exactly you want to track.)
The alternative would be to have a separate table for each kind of activity:
(And you could add a TYPE field in FOLLOW_ACTIVITY to distinguish between "follow" and "unfollow".)
Another alternative would be to inherit users and items from a common parent "class" and then link to that class:
This design is probably an overkill in this case, but could be useful if you later add many other kinds of objects that could be tracked.

Items{ItemID,descr,UserIDCreator,date-time}
User{UserID,descr}
Followings{UserIDFollowed,UserIDFollower,date-time}
now if you wont all items created by eser use user code on items
the same on followings I add date-time for chrono select
You can create atriggered table or a view this depends on cardinality of data
If the same object can be share between users
Items{ItemID,descr,}
UserItems{UserID,descr,ItemId,date-time}
User{UserID,descr}
Followings{UserIDFollowed,UserIDFollower,date-time}
I hope to be useful

Related

How to merge two tables into one DB schema

I'm new to database logic. I have Owners and Borrowers tables for a rental system. Both of them share similar fields like "email, username, password, etc." and also they differ from each other. My question is: How can I merge these similar fields into one table, because I'm pretty sure that my implementation is wrong. Another problem is that I can't properly determine relationship between Items and Item_statuses
When you design your tables, you don't organize them according to the similarities among the titles of the columns, but according to the relations between them.
Your design is working, you may just remove the 'item_statuses' table and create a 'status' column in the 'items' table.
But, let's do some brainstorming to improve the design and consider more of the business logic. We should ask some questions like:
How frequent will the owner be a borrower?
Should I keep track of all the statuses of the item?
If it is frequent for a person to be a borrower and an owner, we will end with duplicated records in our database, so we will make only one table called 'users' with the required fields, and refer the foreign keys in the 'items' table for the users.
If you should keep track of all the statuses of the item, create a separate table called 'items_log' with fields like 'Date' and with a foreign key that references to the item in the items table.
I would also keep track of all the borrowers of the item, so, I can make a 'item_borrowers' table with 'borrower' that references to the user, and 'item' that references to the item with fields like 'Date'.
Also keep in mind that you should store hashed password in the database not plain-text.

Relational Table design

I am designing a feature for a database, but I am stuck on design.
I have a table called AgendaItems, this table is a table with Agenda Items that could be assign to possible multiple users.
Users is a table that contains a record of user names, containing a fixed amount of 17 names.
How would I design these tables possibly another table that keeps track of who is working on what Agenda Item. Keep in mind multiple users could work on an agenda Item and users could work on multiple items.
I am not sure who to design this, and wondering if it would even work?
Thanks
I don't know if I understood your problem but I think your relationship is N-N.
So, you need to create another table (UsersAgendaItems). This table must contain the AgendaItems ID and Users ID, where both of then are FK.
Your PK could be a composite PK. This way you can know what user is related with what AgendaItems.
But I don't know if that is what you want. If this is not your case, please, try to explain a little bit more!
Thanks!

Simple database table design

I'm trying to design a database structure using best practice but I can't get my head around something which I'm sure is fundamental. The DB is for the users(100+) to subscribe to which magazines(100+) they read.
I have a table for the usernames, user info and magazine titles, but I'm unsure where to list the magazines that each user follows. Do I add a column in the user table and link it to the magazine table or would each user be setup with their own "follow" table that lists the magazine there? I'm getting myself confused I think so any help would be great.
Regards
Ryan
What you're struggling with is called a many-to-many relationship.
To solve this problem, you need a third table--perhaps called user_magazines. This third table should two key fields, one from the user table and the other from the magazine table. For example, user_id column and a magazine_id column. This is called a compound key. With both of these columns, you are now able to discern which books have been read by a whichever user.
This is best understood visually:
In the picture above you can see that the third table (the middle table, stock_category) enables us to know what stock item belongs to which categories.
First of all, you must understand a many-to-many relationship, like take your example of users and magazines. First understand the scenario : A single user can follow many magazines, and a single magazine can be followed by many users, so there exists a many-to-many relationship between users and magazines.
Whenever there exists many-to-many relationship between two entities, we have to introduce a third entity between them which is called an associative entity!
so you have to introduce a third entity named as per your choice and it will be containing information about which user is following which magazine
you can go to http://sqlrelationship.com/many-to-many-relationship/ for better understanding using diagrams
You should have a users table, with an auto-incrementing primary key, username, and anything else you want to store about that user.
Next, a magazines table which contains another auto-incrementing primary key, the name of the mag and anything else you need to store about that magazine.
Finally, a subscriptions table. this should have an auto-incrementing primary key (actually that's not really necessary on this table but personally I would add it), a user_ID column and a magazine_ID column.
To add a subscription, just add a new record to the subscription table containing the ID of the user and the ID of the relevant magazine. This allows for users to subscribe to multiple magazines.
If you want to get fancy you can add referential integrity constraints to the subscriptions table - this tells the database management system that a particular column is a reference to another table, and can specify what to do upon modifying it (for example you could have the DBMS automatically delete subscriptions owned by a particular user if that user is deleted)
You definitely do NOT want to add a column to the user table and have it refer to the magazine table. Users would only be able to follow or subscribe to one magazine which doesn't reflect the real world.
You'll want to have a join table that has a userId and a magazineId. For each magazine that a user subscribes to there will be one entry in the join table.
I'm inferring a little bit about your table structure but if you had:
User (id, login)
Magazine (id, name)
User_Magazine (userId, magazineId)
Perhaps this last table should be called subscription because there may be other information like the subscription end date which you'd want to track and that is really what it is representing in the real world.
You'd be able to put an entry into the User_Magazine table for every subscription.
And if you wanted to see all the magazines a user with the login jdoe had you'd do:
SELECT name
FROM User, Magazine, User_Magazine
WHERE login = 'jdoe'
AND User.id = User_Magazine.userId
AND Magazine.id = User_Magazine.magazineId
You should create a separate table called UserMagazineSubs. Make the UserID + MagazineTile ID as a composite key.
This table will capture all User and Magazine relationship details.
A User_To_Magazine table, that has two columns - UserId and MagazineId, and the key is composite containing both columns

User-specific database records

This is more of a theoretical questions. Anyways,
Assume that I have a database (50 tables)
And Data in ALL of those tables should be hold specifically to one user.
What I mean is, usually we do foreign keys for each table that is user-specific. and retrieving data using something like:
select Column1,Col2,Col3 from Table where UserId=#UserId
This clutters queries significantly. Is the other way of storing such data?
What you're referring to has a name. It's called multi-tenant. The link gives some general information on multi-tenant structures.
This all depends on your RDBMS though. Oracle provides a tool which makes this very easy.
The
WHERE User_ID = #User_ID
becomes a policy which you can apply to tables. You also create a protected stored procedure to update #User_id to ensure that it cannot be changed without authority. Then every query to a table with such a policy adds the where clause in the background. It's automatic and there's no way to avoid it.
There might be other ways, but I wouldn't say they are better. If every record in every table needs to belong to a specific user then you need a way to define that.
A possible method to reduce the number of UserId columns would be if you have child tables and you simply assumed that the parent table defined ownership and that it was implied that it's child records belonged to that user.
Example:
CarMake:
MakeId
MakeName
UserId
CarModel:
ModelId
MakeId
ModelName
Notice that CarModel does not have a UserId column, but you could assume that it inherits the same UserId of the parent CarMake record. If you cannot assume that children should always inherit the parent UserId then your original method is best.

What to do if 2 (or more) relationship tables would have the same name?

So I know the convention for naming M-M relationship tables in SQL is to have something like so:
For tables User and Data the relationship table would be called
UserData
User_Data
or something similar (from here)
What happens then if you need to have multiple relationships between User and Data, representing each in its own table? I have a site I'm working on where I have two primary items and multiple independent M-M relationships between them. I know I could just use a single relationship table and have a field which determines the relationship type, but I'm not sure whether this is a good solution. Assuming I don't go that route, what naming convention should I follow to work around my original problem?
To make it more clear, say my site is an auction site (it isn't but the principle is similar). I have registered users and I have items, a user does not have to be registered to post an item but they do need to be to do anything else. I have table User which has info on registered users and Items which has info on posted items. Now a user can bid on an item, but they can also report a item (spam, etc.), both of these are M-M relationships. All that happens when either event occurs is that an email is generated, in my scenario I have no reason to keep track of the actual "report" or "bid" other than to know who bid/reported on what.
I think you should name tables after their function. Lets say we have Cars and People tables. Car has owners and car has assigned drivers. Driver can have more than one car. One of the tables you could call CarsDrivers, second CarsOwners.
EDIT
In your situation I think you should have two tables: AuctionsBids and AuctionsReports. I believe that report requires additional dictinary (spam, illegal item,...) and bid requires other parameters like price, bid date. So having two tables is justified. You will propably be more often accessing bids than reports. Sending email will be slightly more complicated then when this data is stored in one table, but it is not really a big problem.
I don't really see this as a true M-M mapping table. Those usually are JUST a mapping. From your example most of these will have additional information as well. For example, a table of bids, which would have a User and an Item, will probably have info on what the bid was, when it was placed, etc. I would call this table... wait for it... Bids.
For reporting items you might want what was offensive about it, when it was placed, etc. Call this table OffenseReports or something.
You can name tables whatever you want. I would just name them something that makes sense. I think the convention of naming them Table1Table2 is just because sometimes the relationships don't make alot of sense to an outside observer.
There's no official or unofficial convention on relations or tables names. You can name them as you want, the way you like.
If you have multiple user_data relationships with the same keys that makes absolutely no sense. If you have different keys, name the relation in a descriptive way like: stores_products_manufacturers or stores_products_paymentMethods
I think you're only confused because the join tables are currently simple. Once you add more information, I think it will be obvious that you should append a functional suffix. For example:
Table User
UserID
EmailAddress
Table Item
ItemID
ItemDescription
Table UserItem_SpamReport
UserID
ItemID
ReportDate
Table UserItem_Post
UserID -- can be (NULL, -1, '', ...)
ItemID
PostDate
Table UserItem_Bid
UserId
ItemId
BidDate
BidAmount
Then the relation will have a Role. For instance a stock has 2 companies associated: an issuer and a buyer. The relationship is defined by the role the parent and child play to each other.
You could either put each role in a separate table that you name with the role (IE Stock_Issuer, Stock_Buyer etc, both have a relationship one - many to company - stock)
The stock example is pretty fixed, so two tables would be fine. When there are multiple types of relations possible and you can't foresee them now, normalizing it into a relationtype column would seem the better option.
This also depends on the quality of the developers having to work with your model. The column approach is a bit more abstract... but if they don't get it maybe they'd better stay away from databases altogether..
Both will work fine I guess.
Good luck, GJ
GJ