views:

86

answers:

5

Hi, i have a countries list. Each user can check multiple countries. Once saved, this "user country list" will be used to get whether other users fit into countries certain user chose.

Question is what would be the most efficient approach to this problem...

I have one, one to save user selection as delimited list like Canada,USA,France ... in single varchar(max) field but problem with it would be that once user from Germany enters page i perform this check on. To search for Germany i would be needed to get all items and un-delimit each field to check against value or to use sql 'like' which again is pretty damn slow..

If you have better solution or some tips i would be glad to hear.

Just to make sure, many users will have their own selections of countries from which and only they want to have users to land on their page. While millions of users will reach those pages. So the faster approach will be the better.

technology, MSSQL and ASP.NET

thanks

+7  A: 
David Stratton
David, I thought of that in the first place but lets say i have 500 users while each user has at least 2 variants of country lists with 4 countries each. Would Many-To-Many will be much faster approach in case i will need to check two large tables each time some user clicks ?I'm sure following best DB optimization practices would be to use many-to-many but maybe this is the time when too much optimization can create bigger problem ?
eugeneK
@eugeneK, parsing a string to find those values will be the slowest way to go
KM
No... Many to many is still the way to go in this case. As @KM said, parsing out those values would be a mess, and a bigger performance hit for a number of reasons... For just one reason, if you need to filter in a where clause based on this field, you'll have to use "like", which is much slower than searching using "=" or better yet, searching uing "=" on a properly indexed field.
David Stratton
great poster! I wish it was still available! I printed it out on regular paper but it's just too small to do it justice!
Leslie
@eugeneK: You can impossibly be serious about what you say. A proper many-to-many relation with indexes set accordingly will beat your string writing/parsing madness by far in both small and large number of records in your database. PLEASE read a good book about database normalization. A good database design is so important, not only for performance, but also for maintainability and extensibility later on... and: +1 for you David of course :) Could not have said it better.
Philip Daubmeier
@David Stratton and @KM, thanks!
eugeneK
+2  A: 

In this case, you want will want to create a table called UserCountries (or some such) which would store the UserID and CountryID. This is a standard relational construct. To beginners, it seems strange and too involved, but this structure makes it very easy and very fast to write flexible queries against this type of data. No delimiting required!

Dave Markle
+1. Same basic answer as mine, and nicely phrased.
David Stratton
+3  A: 

Do not save delimited fields into your database. Your database will not be normalized.

You need a many-to-many table for users and countries:

UserId
CountryId

If you do start using a delimited field, you end up needing to parse it (either in SQL or your Code). It is more difficult to query and optimize.

Oded
And +1 to you as well.
David Stratton
Thanks Oded, you have the same reply i gave to David///
eugeneK
@eugeneK - In regards to that reply: 500 users is not a lot. Hundreds of thousands and more are starting to be a lot for a SQL Server. One way or another, this is the correct design for your question.
Oded
+1  A: 

I think it would be better to use a UserCountry table, which contains a link to the User and the Country table. This creates a lot more possibilities to query against the database. Example queries that are much simpler this way:

  • Number of Countries per user
  • All users which selected a particular country
  • Sort all popular countries
Ruben
thanks, you've made some good points i haven't thought of...
eugeneK
A: 

Do not store multiple countries in a single field. Add 2 additional tables - Countries (ID, Name) and UserCountries (UserID, CountryID)

SQLDev