Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
Using MS SQL: The scenario is I have already a Contact master table (tbl_Customer)for all contacts in the company. The staffs suggested that they do not want to see all the contact and that they will only choose which contacts are applicable for them. The contact table is not gonna be store on the client like an outlook's pst file but on server side particularly on the database.
The methods i can use are:
1.) every time i add a staff i create a new independent table for the staff and the staff just adds the contact he/she needs from the master table via a program.
2.) I can change the contact master table to add say 50 fields with names staff01, staff02 and so on... I will make use of this fields as a marker that this rows of customer is a contact of the staff on the fields.
3.) I do a completely new contact list. Adds a field name "User". Mark the initial records via putting "ALL" on the field name. If a staff adds a contact, the table add a record with his/her name on the field "User". There will be an Auto numbered field as primary index.
Currently I'm tempted to use 3.) are there any other better method for my problem?
Why don't you have a staff table with a staff id - then every contact the staff in question wants can be a row in staffContacts. Column 1 is staffID and col 2 is contactID. Then you can join on the contact table to retrieve the details you want.
The contacts table then only needs be updated...You only need to add one table with two columns. You may wish to impose constraints that let fields be entered that are unique to staffID and contact ID and are valid staff members and contacts.
Nick.
If I understand correctly you want to have a list of the contacts that is filtered specifically based on a particular users preferences?
Personally I would create another table like this:
Create Table UserContactPreferences
(
ID int identity(1,1),
UserID int,
ContactID int,
)
And then each individual user can pick what contacts they want visible and you can add an entry here for it.
Then when you query the database you can do something like this, passing in the CurrentUser in the query:
SELECT c.*
FROM tbl_Customer c
JOIN UserContactPreferences up on c.contactID = up.contactID
WHERE up.UserID = #CurrentUser
This will then only return Customers that the user has specifically said they want to see.
In case many staff members have the same relevant contact - you should use a connection table, in which there will be 2 columns - one with the contact id , and one with the staff member id, use this table to query for staff's relevant contacts.
In case each contact has only one staff, than simply add a column with the relevant staff id, which will be a foreign key to the staff's table.
In any case and for other users to learn from:
method 1 you suggested is a big no no in SQL DB design, you need a really good reason for a DB with dynamically created tables.
method 2 is bad practice since most of the space will be wasted (unless defined as sparse columns but even though.. still space consuming) and also too specific - what will happen when you add a new staff member ? add a new column ? lock the whole DB for it and add many wasted space allocated?
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
I have a product table with a primary key #productid (bigint), a product number (int), and a version (int)
Any time someone makes changes to the product record ONLY, I plan on inserting a new row in the database with the same product number and version number + 1. This will provide me with the historical tracking I need for the record because I can see the version changes throughout time.
/* Selecting the current version is simple */
Select top 1 *
from products
where productnumber = #productnumber
order by version desc
However, my problem comes in with the Foreign key one-to-many or many-to-many relationship tables. This table points to many others (i.e. product pricing with date ranges, product categories, etc.) which also need to be tracked.
/* Product categories, pricing */
/* Should I use #productnumber here? How do I track changes to these records? */
select name
from productcategories
where productid = #productid
select price
from productpricing
where productid = #productid and
StartDate > #StartDate and
EndDate <#Enddate
So now any time there is a version change, I plan to to re-insert new category and pricing records with the new Primary Key product id that was generated..This is going to lead to a ton of duplicates, especially if no changes were made to these records.
Also the issue comes in with - what happens if a category is removed but there were no changes to the product record? I would want to see who removed the category. Essentially, a full audit is needed on each table.
I have seen some different examples but most of them only seem to deal with a record in one table and not a record that is a part of one-to-many or many-to-many relationships. I was hoping this could be done without the need of additional tables.
Are there any better methods or practices? Is this going to be a performance nightmare?
If you are using a newer version of SQL Server as you are, you can should look into temporal tables as this might be your best option.
If you need to support older versions, my preferred method is to have a history table with a new PK column, change flag (I,U,D), a date modified, user that made the change, and all of the columns from the primary table. I then index the column related to the PK of the non-history table. Triggers don't impact performance too much if you don't put logic in them.
Example (pseudocode):
Table: Car
Column: CarID INT IDENTITY(1,1) Primary Key
Column: Name varchar
Table: Car_hist
Column: Car_histID INT IDENTITY(1,1) Primary Key
Column: Change char(1)
Column: DateOfChange DateTime2
Column: ChangedByUser (varchar or int)
Column: CarID <-add a unique non-clustered index
Column: Name varchar
You can write a generator in SQL that generates the script to create the history table, indexes, etc. It helps if you have a consistent table design practice.
Now the reason: I rarely have to query history tables, but when I do, it is almost always for a single record to see what happened and who changed it. This method allows you to select from the history on the parent table's PK value quickly and read it as a historical change log easily (who changed what and when). I don't see how you can do that in your design. If you are really slick, you can find or write a grid that diffs rows for you and you can quickly see what changed.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
Let's say I'm working on an online store project. So, I'm gonna have to create a table called 'Product' in my database. Say I also want users to be able to 'like' my products. That requires me to create another table called 'ProductLike' to store users' IDs alongside the ID of the product they like (a junction table).
The main scenario: Every time when a user sends a request to my website to get a product page, I'm gonna have to recalculate the number of likes that product has.
My question is: So, I know the standard approach is not to store 'Calculated values' in the database (normalization). But what about cases like this? (I mean cases in which it might be expensive to calculate something). For instance in the example above, isn't it better to have a column named 'NumberOfLikes' in the 'Product' table to store the calculated number of the product likes for fast retrieval?
Update
isn't it better to have a column named 'NumberOfLikes' in the 'Product' table to store the calculated number of the product likes?
IMHO, the direct answer to this question is "No, unless you have a real performance problem due to the counting of likes".
If you do have a performance problem, and you've identified its source as the count of likes, Then you might want to consider adding a LikesCount column to the products table. If you do add such a column, please note you are going to have to update it on every change to the ProductLike table - delete, update and insert.
This means you are going to have to write a trigger for this table to handle all these cases, but it shouldn't be too hard since you can do everything in a single trigger - something like this:
create trigger ProductLikeChaneged on ProductLike
for insert, update, delete
as
update p
set LikesCount = (select count(*) from ProductLike as pl where pl.productId = p.Id)
from product as p
where exists
(
select 1 from inserted as i where p.id = i.productId
)
or exists
(
select 1 from deleted as d where p.id = d.productId
)
Original version
Based on your description, "calculating" the number of likes for a product is simply a count of rows in the ProductLike table where the product id is the id of the product you are currently displaying to the user.
This can be done very fast, especially if the ProductLike table clustered index is ProductId and then UserId, thus allowing SQL Server to use clustered index seek and not a table scan.
Basically, your ProductLike table should look like this:
Create table ProductLike
(
ProductId int,
UserId int,
Constraint PK_ProductLike PRIMARY KEY (ProductId, UserId)
)
Note that by default, SQL Server will use the primary key as the clustered index of the table.
Then your select statement for the product page can be something like this:
select Name, Description, -- Other product related details
(select count(*)
from productLike as pl
where pl.ProductId = p.Id) as likeCount
from product as p
By "calculated" value, I suspect you mean an accumulation of the number of requests.
The simplest approach in terms of database design and maintenance is to store each request as a row in a table and to summarize when needed. This has certain nice features:
A user can "unrequest" or "unlike" quite easily.
Inserts are (typically) at the "end" of the table, minimizing fragmentation and speeding inserts. Note: This can result in contention for the last page if multiple threads are writing at the same time.
Counts can be flexible, limited to a particular date range or type of user for instance.
The data is drill-downable. That is, for a given count you know exactly what produced it.
Summarization is often very reasonable, if you have the right indexes and partitions on the data.
That said, such summarization does not meet all needs. A traditional approach is to use a trigger to maintain summary tables -- adding lots of complexity for maintenance (you need insert, delete, and update triggers). I think #daniherrera's answer gives guidance on the best approach.
For real life they are real solutions. You should to materialize this field and denormalize database to keep performance. Do you have serveral options to keep this field uptodate:
Materialized views.
Triggers.
Store procedure.
Disclaimer: Your question is a primary opinion-based, I guess will be closed in a while.
Number of product liked by user can be fetched by UserProductLike table, where userid is id of your user.
I'm an intern at a small company who is making some fixes to a 15 year old access database that is used to keep track of customers, jobs, etc. I'm trying to write an update query and can't seem to get to work the way I need it to. Here is my sitation.
I have two tables. One contains Company information. The other contains Contact information. The primary key of the company table is also in the contact table, for a one-to-many relationship. E.g., if a company has 3 contacts, the CompanyID number that is from the primary key of the Company table is associated with the three contacts in the Contacts Table.
Ok. Now the problem is that there is some legacy code in a form, called "Company", that searches simultaneously for both contacts and companies. The problem is that there is a field in the contacts table called "ContactCompany" that is being used by this old search function. If a user changes the Company name with the form, the Company name is updated on the Company table, but NOT in the Contacts table.
I decided that an update query would be the way to go, to sync up the Company Name information on both forms. I tried to design it so that if the ID numbers matched between the tables, the company name in the Company table would get copied over to the contacts table. My code is below:
UPDATE Company INNER JOIN Contacts ON (Company.ID = Contacts.CompanyID) AND (Company.ContactCompany = Contacts.ContactCompany) SET Contacts.ContactCompany = [Company].[ContactCompany] WHERE (([Contacts].[CompanyID]=[Company].[ID]));
When I run the query Access tells me that it is updating X number of records, but the records do not update.
Please note that I used query builder; the SQL code was auto-generated by access when I go into SQL view.
I'm not very experienced with VB; all of my knowledge has been from googling stuff. If someone could give me some pointers on what I'm doing wrong or how to proceed I'd be grateful. Thanks!
Because in your join condition you are selecting the Contact.ContactCompany which already has same ContactCompany name.
AND (Company.ContactCompany = Contacts.ContactCompany)
Remove that "AND" part and your query should look something like this.
UPDATE Company
INNER JOIN Contact ON Company.ID = Contact.CompanyID
SET Contact.ContactCompany = [Company]![ContactCompany]
WHERE (([Contact]![CompanyID]=[Company]![ID]));
P.S. Make sure you have backup of your database before updating
I use the query assitance from Access
You dont need AND (Company.ContactCompany = Contacts.ContactCompany) you are already saying those are different now.
UPDATE Company
INNER JOIN Contact
ON Company.CompanyID = Contact.CompanyID
SET Contact.CompanyName = [Company].[CompanyName];
You could add this line to only update those different
WHERE Contact.CompanyName <> = [Company].[CompanyName]
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
I have a table called Order which holds customer orders.
I want people to be able to add notes to orders. Whats the best way to name this new table? Because other tables may also have notes e.g. Customer, I need the table to be named so that is shows association with the relevant table. Relationship is an Order will have 0-or-many Notes.
So should I name it:
Order_Note
OrderNote
They all seem fine. I also need to create another table that will list the 'types' of Order that have been placed. An Order can have 1 or many 'types'. So how would I name this association in the table name?
Order_Type
OrderType
In this Order_Type table, it will have just two columns OrderID and TypeID. So I need a final table which holds all possible Types of order that can be placed. How do I name this, given that it will be confusing with the table above?
Order_Types
OrderTypes
But this is breaking the rule of not having plurals in table names.
Edit:
The Order table is a data table. Order_Type is a joining table. And finally, OrderTypes is a lookup table. Thanks to Hogan for making this obvious to me. I have also removed hyphenation between words as an option as it may cause future problems.
SOLUTION 1:
Name association between tables using underscore e.g. Order_Type
Name lookup and data tables without underscores e.g. Order, OrderType
I'll also use a schema so that lookup tables show like Lookup.OrderType which helps to clarify what is what.
The way I've done it is listed below
As a side note, these suggestions have to do with how to think about
joined table names and it does not matter if you use camel case or
not, underscores or not etc.
The important note here is that there is fundamentally a difference
between a joining table, a lookup table and a data table. The names
should reflect this and be consistent.
1)
I would make a note table and call it Note. Then I would add a relationship between orders and notes and call it order2note or orderNote or orderNoteRel
This table name defines the two joined tables in some order, sometimes you can put the non-FK first but in many cases it is best to just default to alphabetical.
2)
For tables that define a code (or a type as you put it) I will make a convention of ending the "Type" or "Code" or "CD" etc in the table name.
so orderType or orderCD or orderCode would be for the table that defines order types.
3)
The final table is actually a join between order table and orderType table so it would be
order2orderType or orderOrderCD or orderOrderCodeRel
(or some other combination of the conventions I've shown.)
This is the important one. If you remember that the table you are joining to should have order in its name (it is the orderType table) Then the join between order and order type should have order twice in its name. While this seems redundant at first once you get used to it it makes total sense.
My situation is:
Table member
id
firstname
lastname
company
address data ( 5 fields )
contact data ( 2 fields )
etc
Table member_profile
member_id
html ( something like <h2>firstname lastname</h2><h3>Company</h3><span>date_registration</span> )
date_activity
chat_status
Table news
id
member_id (fk to member_id in member_profile)
title
...
The idea is that the full profile of the member, when viewed is fetched from the member database, in for instance a news overview, the smaller table which holds the basis display info for a member is joined.
However, i have found the need for more often use for the member info that is not stored in the member_profile table, e.g. firstname, lastname and gender, are nescesary when someone has posted a news item (firstname has posted news titled title.
What would be better to do? Move the fields from the member_profile table to the member table, or move the member fields to the member_profile table and perhaps remove them from the member table? Keep in mind that the member_profile table is joined a lot, and also updated on each login, status update etc.
You have two tables named member so i have the feeling your question isn't formed correctly.
What is the relationship between these tables? It looks like you have 3 tables, all one-to-one. So all you need to do is change (fk to member_id in member_profile) to (fk to id in member).
Now you can join in data from either of the 2 extra tables as you wish, without always having to go through member_profile.
[Edit] Also I assume that member_profile.member_id is a fk to member.id. If not, I believe it should :)
Combine them into one table so you're normalizing the name data then create 2 views which replicate the original two tables would be the easy option
Separating the tables between mostly-static fields and frequently-updated fields will improve write performance. So I would stay with what you're doing. If you cache the information from both tables together in a member object, read performance (and thus joining) is less of an issue.