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 5 years ago.
Improve this question
I have the following database tables
User List
------ ------
userId (PK) listId (PK)
fullName description
addedById (FK with userId in User table)
modifiedById (FK with userId in User table)
I need to pull out all data from the List table, but instead of showing the IDs for addedById and modifiedById, I need to pull the fullName from the User table.
This query works, and gives me the data I need. However, I'm not sure if there is a better way of constructing this query? I'm not keen on having multiple sub select queries within my main select query, mainly because of performance issues.
select t1.[description],
t1.addedById,
t1.modifiedById,
(select fullName from dbo.User where userId = t1.addedById) as [AddedByUser],
(select fullName from dbo.User where userId = t1.modifiedById) as [ModifiedByUser]
from dbo.List t1
I'd really appreciate if anyone could suggest improvements to the query, or advise to keep as is.
Thanks.
A more standard SQL method would be:
SELECT t1.description,
t1.addedById,
t1.modifiedById,
add.fullName AS [AddedByUser],
mod.fullName AS [ModifiedByUser]
FROM dbo.List t1
LEFT JOIN dbo.User add
ON add.userId = t1.addedById
LEFT JOIN dbo.User mod
ON mod.userID = t1.modifiedById
However, I suspect this will perform identically to your query and probably has an identical execution plan. The only real advantage to this method is that it's easier to expand. For example, if you wanted to add new columns from the User table this would be easier.
As #Gordon notes, performance should be fine if there's an index on the fields you're joining with.
Is that double join with same table bothering you? It's not slow, its preferred way of doing it instead making the linked subquery.
I am assuming you got indexes on PK and both FK.
Only thing you can minimize is to lessen the number of joined rows. You can do that
by either using the left inner join or filtering in the end with where clause stating both keys you use in join must be not null
I can write both examples for you but this should be self explanatory.
Other mayor thing you can do is to PRESELECT values from users. For example if you have a shit ton of users, and you know only few of them can be in either role. And you can filter which ones by some column in Users you haven't listed, even better if that column has an index.
Then you can maybe profit from pre-selecting only those users and then joining to selection result. Either by temp table if both can be pre-selected or by making a select on spot instead joining to the entire table. Not sure about numbers we are dealing with here for this to become relevant..
Related
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.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 9 years ago.
Improve this question
I am still fairly green when it comes to SQL joins. The below code works but I want to check that I am doing it the best way before I copy and paste errors into other work in the future.
The idea of the below code is to get the PropertyID and Name of a property from the first Table and using the PropertyID join them. In this case I am actually using every field in Table B (thus the *).
So more a peer review than anything.
SELECT TblA.propertyid AS PD,
TblA.propertyname AS PD,
TblB.*
FROM tbpropertydetails AS TblA
INNER JOIN tbpropertydetailssafeguarding AS TblB
ON TblA.propertyid = TblB.propertyid
WHERE TblA.regionid <> '0'
ORDER BY TblA.propertyid ASC
I am programming in VB.net but this is really standalone SQL.
Generally you want to be caution with inner joins because you can lose potential record sets.
An example would be records in TbPropertyDetails that do not have an entry (no matching PropertyId) in TbPropertyDetailsSafeguarding would vanish. There might not be a corresponding entry in the joining table because this information is entered at a later date.
Try using a LEFT JOIN first and then decide how you want to handle the null records i.e. those records in the primary table that had matching records in the joining table.
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.
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?
When I have to select a number of fields from different tables:
do I always need to join tables?
which tables do I need to join?
which fields do I have to use for the join/s?
do the joins effects reflect on fields specified in select clause or on where conditions?
Thanks in advance.
Think about joins as a way of creating a new table (just for the purposes of running the query) with data from several different sources. Absent a specific example to work with, let's imagine we have a database of cars which includes these two tables:
CREATE TABLE car (plate_number CHAR(8),
state_code CHAR(2),
make VARCHAR(128),
model VARCHAR(128),);
CREATE TABLE state (state_code CHAR(2),
state_name VARCHAR(128));
If you wanted, say, to get a list of the license plates of all the Hondas in the database, that information is already contained in the car table. You can simply SELECT * FROM car WHERE make='Honda';
Similarly, if you wanted a list of all the states beginning with "A" you can SELECT * FROM state WHERE state_name LIKE 'A%';
In either case, since you already have a table with the information you want, there's no need for a join.
You may even want a list of cars with Colorado plates, but if you already know that "CO" is the state code for Colorado you can SELECT * FROM car WHERE state_code='CO'; Once again, the information you need is all in one place, so there is no need for a join.
But suppose you want a list of Hondas including the name of the state where they're registered. That information is not already contained within a table in your database. You will need to "create" one via a join:
car INNER JOIN state ON (car.state_code = state.state_code)
Note that I've said absolutely nothing about what we're SELECTing. That's a separate question entirely. We also haven't applied a WHERE clause limiting what rows are included in the results. That too is a separate question. The only thing we're addressing with the join is getting data from two tables together. We now, in effect, have a new table called car INNER JOIN state with each row from car joined to each row in state that has the same state_code.
Now, from this new "table" we can apply some conditions and select some specific fields:
SELECT plate_number, make, model, state_name
FROM car
INNER JOIN state ON (car.state_code = state.state_code)
WHERE make = 'Honda'
So, to answer your questions more directly, do you always need to join tables? Yes, if you intend to select data from both of them. You cannot select fields from car that are not in the car table. You must first join in the other tables you need.
Which tables do you need to join? Whichever tables contain the data you're interested in querying.
Which fields do you have to use? Whichever fields are relevant. In this case, the relationship between cars and states is through the state_code field in both table. I could just as easily have written
car INNER JOIN state ON (state.state_code = car.plate_number)
This would, for each car, show any states whose abbreviations happen to match the car's license plate number. This is, of course, nonsensical and likely to find no results, but as far as your database is concerned it's perfectly valid. Only you know that state_code is what's relevant.
And does the join affect SELECTed fields or WHERE conditions? Not really. You can still select whatever fields you want and you can still limit the results to whichever rows you want. There are two caveats.
First, if you have the same column name in both tables (e.g., state_code) you cannot select it without clarifying which table you want it from. In this case I might write SELECT car.state_code ...
Second, when you're using an INNER JOIN (or on many database engines just a JOIN), only rows where your join conditions are met will be returned. So in my nonsensical example of looking for a state code that matches a car's license plate, there probably won't be any states that match. No rows will be returned. So while you can still use the WHERE clause however you'd like, if you have an INNER JOIN your results may already be limited by that condition.
Very broad question, i would suggest doing some reading on it first but in summary:
1. joins can make life much easier and queries faster, in a nut shell try to
2. the ones with the data you are looking for
3. a field that is in both tables and generally is unique in at least one
4. yes, essentially you are createing one larger table with joins. if there are two fields with the same name, you will need to reference them by table name.columnname
do I always need to join tables?
No - you could perform multiple selects if you wished
which tables do I need to join?
Any that you want the data from (and need to be related to each other)
which fields do I have to use for the
join/s?
Any that are the same in any tables within the join (usually primary key)
do the joins effects reflect on fields specified in select clause or on where conditions?
No, however outerjoins can cause problems
(1) what else but tables would you want to join in mySQL?
(2) those from which you want to correlate and retrieve fields (=data)
(3) best use indexed fields (unique identifiers) to join as this is fast. e.g. join
retrieve user-email and all the users comments in a 2 table db
(with tables: tableA=user_settings, tableB=comments) and both having the column uid to indetify the user by
select * from user_settings as uset join comments as c on uset.uid = c.uid where uset.email = "test#stackoverflow.com";
(4) both...