| Author |
Topic |
|
hacktothefuture
Starting Member
10 Posts |
Posted - 2007-12-17 : 18:12:39
|
Hello AllI am not the greatest at designing complex queries and feel that I rely on subqueries much more than I should. Well this has lead me to a performance problem in one of my queries. Im trying to get much better at this and would certainly welcome any help that I can get (Including any helpful books on the subject you can recommend).This is the the situation. I have two tables. One is a reference table used for storing possible user preferences. Its structure is like this:PreferencesId PrefName----------------------1 Blue Cars2 Candy Bars3 Long Walks4 SunsetsThe other table stores each users selected preferences. It must not only store current preferences but also prefences the user has selected in the past and has since deactivated. Like this:UserPrefencesId UserId Pref Status--------------------------------1 1 1 02 1 2 13 2 1 04 2 2 15 2 3 1I need to display all preferences options for a user and whether the user has selected it. Like this:Preferences for UserId: 1Id PrefName IsSelected-----------------------------------1 Blue Cars 02 Candy Bars 13 Long Walks 04 Sunsets 0Here is the query I used to solve the problem:declare @userid intset @userid = 1select id, PrefName,ISNUMERIC((select UserId FROM UserPreferences up WHERE up.pref = p.Id and up.UserId = @userId and status = 1)) As IsSelectedfrom Preferences p Well this query works great, except for one thing, its slow, very slow. The Preferences table has grown very large so that Users can have a large number of preferences and the users table is also quite large. Eventually this query will not work, actually its pretty much there now.Is the structure of the tables flawed or is the query? I cannot really change the table structure but I would like to know if that is recommended but is there a way to query these tables more efficiently and quickly.Thanks very much for any help you can give. |
|
|
visakh16
Very Important crosS Applying yaK Herder
52326 Posts |
Posted - 2007-12-18 : 00:11:42
|
| Try this. Also put an index on id columns on both tables (that used in join )and also UserId column of second tableSELECT p.Id,p.PrefName,ISNULL(u.Status,0) AS 'IsSelected' FROM Preferences pLEFT OUTER JOIN UserPreferences uON u.Pref=p.IdWHERE u.UserId={req user id} |
 |
|
|
jezemine
Master Smack Fu Yak Hacker
2886 Posts |
Posted - 2007-12-18 : 01:21:22
|
UserPreferences should not have the ID column. the PK in this table should be a composite key on UserID, PrefID. With your current design, you could have a user that simultaneously loves and hates long walks and sunsets. you don't want that to be allowed do you? Can you post the DDL for these two tables? are the "number" columns integer types, or are they char/varchar/text/etc? elsasoft.org |
 |
|
|
hacktothefuture
Starting Member
10 Posts |
Posted - 2007-12-18 : 11:50:17
|
| Thanks for your replies! visakh16, thanks for the hints on the indexes they are in place but your query did not return the desired results. All records for user 1 were returned instead of all preferences and which ones user 1 had selected.jezemine, this is a very interesting idea that I had not thought about. The tables are designed to indicate the current preferences of the user (not the things he doesn't). If at one point the user did not like long walks but now he does that is ok. All number columns are in fact integers. As far as the DDL, this is more of an example of my actual tables. The tables themselves have long complicated field names and have other fields that are not relevant to the question and I didnt want to confuse the issue. |
 |
|
|
matty
Posting Yak Master
161 Posts |
Posted - 2007-12-19 : 04:48:49
|
| SELECT P.ID,PrefName,ISNULL(status,0) As IsSelectedFROM Preferences pLEFT JOIN UserPreferences up ON up.pref = p.Id AND up.UserId = 1 |
 |
|
|
caisys
Starting Member
16 Posts |
Posted - 2007-12-19 : 07:34:49
|
| How about this?SELECT P.ID,PrefName,ISNULL(status,0) As IsSelectedFROM Preferences pLEFT OUTER JOIN (Select [id] from UserPreferences where userid = 'YOUR USER' and status = 1) upON up.id = p.Id |
 |
|
|
hacktothefuture
Starting Member
10 Posts |
Posted - 2007-12-20 : 18:08:07
|
| Im afraid those did not work as expected either. Thanks for your help though... |
 |
|
|
hacktothefuture
Starting Member
10 Posts |
Posted - 2008-01-23 : 15:13:13
|
| Can anyone provide any further insight on this query issue? |
 |
|
|
jdaman
Constraint Violating Yak Guru
354 Posts |
Posted - 2008-01-23 : 15:44:55
|
| [code]DECLARE @Userid INTSET @Userid = 1SELECT p.PrefName, ISNULL(a.Status, 0) as StatusFROM Preferences pLEFT OUTER JOIN ( SELECT u.UserId, u.Pref, u.Status FROM Preferences p LEFT OUTER JOIN UserPreferences u ON p.Id = u.Pref WHERE u.UserId = @UserId ) a ON p.Id = a.Pref[/code] |
 |
|
|
|