views:

59

answers:

1

I have 4 SQL server(2008 version) tables

1) USER- to store user information (Fields : UserId,UserName)
2) FILES - to store files uploaded by user (FileId,FileName,UserId)
3) PHOTOS -to store files uploaded by user (PhotoId,PhotoName,UserId)
4) GROUPS= to store groups created by user ( GroupId,GroupName,UserId)

Now I want to get a USER record with id=5 along with Total number of Files uploaded by userid 5,Total Photos uploaded by user id 5,Total groups created by userid 5.Can i get all these with a single query ? OR should i write a SELECT COUNT of each table with USER ID=5 in the where clause ( 3 queries.. ?)

I can write an inner join with USER and FILES and do the count to get the number of files uploaded by a purticular user.But how to add the number of photos and number of groups to the result ?

What is the best approach to do this ?

Sample Data

USER

USERID     USERNAME
------     ---------
1          Shyju
2          OMG
3          Gus

FILES

FILEID      FILENAME    USERID
------      --------    ------
101         Sample1     1
102         Secondone   1
103         NewOne      2
104         BetterOne   3
105         Ocean       3
106         Sea         3

GROUPS

GROUPID   GROUPNAME   USERID
-------   ---------   ------
 51       Group-A     1
 52       Group-B     2
 53       Group-C     2
 54       Group-D     2
 55       Group-E     3
 56       Group-F     3

The Result i am looking for is

For User ID=1

 USERID  USERNAME  FILECOUNT  GROUPCOUNT
 ------  --------  ---------  ----------
  1      Shyju     2          1

For UserId=2

 USERID  USERNAME  FILECOUNT  GROUPCOUNT
 ------  --------  ---------  ----------
  2      OMG        1          3
+4  A: 

Use:

   SELECT u.userid,
          u.username,
          COALESCE(f.numFiles, 0) AS numFiles,
          COALESCE(p.numPhotos, 0) AS numFiles,
          COALESCE(g.numGroups, 0) AS numGroups
     FROM [USER] u
LEFT JOIN (SELECT t.userid,
                  COUNT(*) AS numFiles
             FROM [FILES] t
         GROUP BY t.userid)f ON f.userid = u.userid
LEFT JOIN (SELECT t.userid,
                  COUNT(*) AS numPhotos
             FROM [PHOTOS] t
         GROUP BY t.userid) p ON p.userid = u.userid
LEFT JOIN (SELECT t.userid,
                  COUNT(*) AS numGroups
             FROM [GROUPS] t
         GROUP BY t.userid) g ON g.userid = u.userid
    WHERE u.userid = 2

You have to use OUTER joins for this to be in one query; INNER joins for all the tables would require that the user have at least one record in FILES, PHOTOS and GROUPS table to be in the resultset. An OUTER join means that users with records in at least one of the tables (FILES, PHOTOS or GROUPS) will be returned.

But JOINs also risk inflating the resultset, which is the issue that occurred in the previous version of my answer. By changing the query to use derived tables/inline views for the FILES, GROUPS and PHOTOS counts, the problem is solved and there's no need for a GROUP BY outside of the derived tables/inline views.

OMG Ponies
I think you will need to add `GROUP BY u.userid` so that you only have 1 row in the result set. Otherwise this should work fine.
Gus
@Gus: Fixed, thx. Too busy explain why to use OUTER joins :/
OMG Ponies
This left join query gave me a wrong result.Its works If its only 2 tables(usser with file/photo/group).More than that,itsgiving wrong count
Shyju
@Shyju: Based on the limited info, the only reason I can see is that usernames aren't unique--so I updated the query to group by the userid and username columns. If things still aren't correct, you'll have to provide data and expected output based on it for anyone to help you. Duplicates are possible in the FILES, PHOTOS and GROUPS tables--is this your issue?
OMG Ponies
I just updated the question with sample data and expected output
Shyju
@Shyju: Thank you - I tested the updated answer on SS2008, and it returns your expected results... ...well, you didn't provide values for PHOTOS, but it was enough to see the issue.
OMG Ponies