SQL: получение подсчета из многих таблиц для пользовательской записи в таблице USER. Каков наилучший подход? - PullRequest
2 голосов
/ 01 октября 2010

У меня есть 4 таблицы SQL Server (версия 2008)

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)

Теперь я хочу получить запись ПОЛЬЗОВАТЕЛЯ с id = 5 вместе с общим количеством файлов, загруженных по идентификатору пользователя 5, Всего фотографий, загруженных пользователемid 5, Всего групп, созданных с помощью идентификатора пользователя 5. Могу ли я получить все это с помощью одного запроса?ИЛИ я должен написать SELECT COUNT каждой таблицы с USER ID = 5 в предложении where (3 запроса ..?)

Я могу написать внутреннее соединение с USER и FILES и выполнить подсчет, чтобы получить числофайлов, загруженных пользователем-носителем. Но как добавить к результату количество фотографий и количество групп?

Каков наилучший подход для этого?

Пример данных

ПОЛЬЗОВАТЕЛЬ

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

ФАЙЛЫ

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

ГРУПП

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

Результат, который я ищу, равен

Для идентификатора пользователя =1

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

для UserId = 2

 USERID  USERNAME  FILECOUNT  GROUPCOUNT
 ------  --------  ---------  ----------
  2      OMG        1          3

1 Ответ

4 голосов
/ 01 октября 2010

Использование:

   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

Вы должны использовать OUTER соединения, чтобы это было в одном запросе;Соединения INNER для всех таблиц требуют, чтобы у пользователя была хотя бы одна запись в таблице FILES, PHOTOS и GROUPS, которая должна быть в наборе результатов.Соединение OUTER означает, что будут возвращены пользователи с записями, по крайней мере, в одной из таблиц (FILES, PHOTOS или GROUPS).

Но СОЕДИНЕНИЯ также рискуют накачать результирующий набор, который возник в предыдущей версиимоего ответа.Изменяя запрос на использование производных таблиц / встроенных представлений для счетчиков FILES, GROUPS и PHOTOS, проблема решается, и нет необходимости в GROUP BY вне производных таблиц / встроенных представлений.

...