|  | Posted by Erland Sommarskog on 07/25/07 22:22 
pbd22 (dushkin@gmail.com) writes:> I have been advised to follow one of two possible templates in the
 > constructon
 > of my GROUP BY clause:
 
 It was not my advices, I hope!
 
 > I get this error once I have been forced to add every column name in
 > the GROUP BY statement. But, I am trying to just add one...
 > tab1.emailAddress (from the Users table). Shouldn't I just be grouping
 > by this column alone?
 >
 > Assuming that you agree with this solution to my duplicate problem,
 
 No, I don't. Looking at your tables it's even more clear what I suspected:
 you need to redesign your tables.
 
 All your tables have a IDENTITY column as the primary key. There are
 definitely cases where an artificial key makes sense. Either because
 the natural key is unpractical, or a real natural key cannot be
 identified. But when you have artificial keys in all tables, and then
 try to use a non-key value as a key, that is when you are in trouble.
 
 Am I to guess that to use your system, the user logs in with his e-mail?
 In such case, why in this table:
 
 > CREATE TABLE [dbo].[Users](
 >      [registerDate] [datetime] NULL,
 >      [password] [varchar](50) NULL,
 >      [role] [varchar](50) NULL,
 >      [securityQuestion] [varchar](50) NULL,
 >      [securityAnswer] [varchar](50) NULL,
 >      [zipCode] [varchar](50) NULL,
 >      [alternateEmail] [varchar](50) NULL,
 >      [emailAddress] [varchar](50) NULL,
 >      [bday_month] [varchar](50) NULL,
 >      [bday_day] [varchar](50) NULL,
 >      [bday_year] [varchar](50) NULL,
 >      [userID] [int] [primary key] IDENTITY(1,1) NOT NULL,
 
 Is the email address nullable. In fact, all columns are nullable. A user
 could be just an IDENTITY value and a bunch of NULL values. How useful
 is that?
 
 Please answer these question:
 1) Can there be a user for which there is no email address registered?
 2) Can there be two users with the same email address?
 
 Depending on the business rules, the answer can very well be yes on
 both questions, but in such case your efforts with the stored procedure
 appear futile. So my assumption is that the answer is no both questions,
 and that emailAddress should be the primary key of this table.
 Alternatively, there should be a UNIQUE constraints.
 
 So what should you use in the other tables? Well, this is a case where
 it makes sense to use an artificial PK as a surrogate. If a user changes
 his email address - which appears to be a reasonable operation to permit -
 you will only need to update the email address in once place. Where foreign
 keys can be set up to be cascading, it's far easier to use UserID in
 other tables.
 
 Next table:
 
 > CREATE TABLE [dbo].[SavedSearches](
 >      [saved_id] [int] IDENTITY(1,1) NOT NULL,
 >      [saved_query] [text] NULL,
 >      [email_address] [varchar](50) NULL,
 
 Again, all columns are nullable but the IDENTITY column. What about
 the email address here? What point does it make to have it NULL?
 And more importantly, can there be an email address here that does not
 exist in Users?
 
 I strongly suspect that you should replace email_address with a
 UserID and an FK to the users table.
 
 As for the saved_id, I don't think table makes much sense. You would
 be better of having a PK which is (UserID, searchno), where searchno
 is a running number for the user. Or simply (UserId, saved_name). (I
 assume that users are permitted to save more than one search.)
 
 > CREATE TABLE [dbo].[PersonalPhotos](
 >      [photoId] [int] IDENTITY(1,1) NOT NULL,
 >      [photo_name] [varchar](50) NULL,
 >      [photo_location] [varchar](100) NULL,
 >      [photo_size] [varchar](50) NULL,
 >      [user_name] [varchar](50) NULL,
 >      [photo_caption] [varchar](50) NULL,
 >      [photo_default] [bit] NULL,
 >      [photo_private] [bit] NULL,
 >      [photo_date] [datetime] NULL,
 >      [no_photo] [bit] NULL,
 >  CONSTRAINT [PK_PersonalPhotos] PRIMARY KEY CLUSTERED
 > (
 >      [photoId] ASC
 > )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY
 >= OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
 > ) ON [PRIMARY]
 
 There is no email address in this table, but there is a user_name? Am I
 to guess that is another name for the email address? Again, replace it
 with UserID and a FK to Users.
 
 The PK of this table should probably be (UserID, photo_name).
 
 > CREATE TABLE [dbo].[LastLogin](
 >      [login_id] [int] IDENTITY(1,1) NOT NULL,
 >      [login_date] [datetime] NULL,
 >      [email_address] [varchar](50) NULL,
 
 Another email_address. Can an email address log in without being in
 Users? Again, put in the UserID here.
 
 As for the PK, this is a little more tricky. Theoretically, (UserID,
 login_date) is the right pick. But time values are not really good for
 PKs, since time is a continuous entity, and all values in a computer
 are discreet. Then again, the likelyhood that a person will login within
 the same 3.33 ms, the resolution of datetime, is likely to be extremely
 small, so for this table it works.
 
 > CREATE TABLE [dbo].[EditProfile](
 >      [edit_id] [int] IDENTITY(1,1) NOT NULL,
 >      [headline] [varchar](50) NULL,
 >      [about_me] [text] NULL,
 >      [edit_date] [datetime] NULL,
 >      [email_address] [varchar](50) NULL,
 >      [public_name] [varchar](50) NULL,
 >      [interests] [text] NULL,
 
 Again, can there be a row here, but not one in Users? Assuming that
 edit_date is date and time, (UserID, edit_date) can probably serve as PK.
 
 I predict that once you have made these changes, you will find your
 procedure a lot easier to write. That does not mean that I how it should
 look like. After all, I still don't see the full picture of what you are
 trying to do.
 
 --
 Erland Sommarskog, SQL Server MVP, esquel@sommarskog.se
 
 Books Online for SQL Server 2005 at
 http://www.microsoft.com/technet/prodtechnol/sql/2005/downloads/books.mspx
 Books Online for SQL Server 2000 at
 http://www.microsoft.com/sql/prodinfo/previousversions/books.mspx
  Navigation: [Reply to this message] |