从多个表中选择计数

时间:2015-01-10 15:21:48

标签: sql

我有三个表TableThreeItems,TableTwoItems和TableOneItems,我需要获取Person在每个表中的访问次数。

我尝试了以下内容:

SELECT Person.[PersonId]

,  Count(TableOneItemId ) as TableOneItemCount
, Count(TableTwoItemIdId ) as TableTwoItemCount
, Count(TableThreeItemId )  as TableThreeItemCount


FROM  [dbo].[Person]
LEFT JOIN TableOneItem ON TableOneItem.PersonId=Person.PersonId
LEFT JOIN TableThreeItemId ON TableThreeItemId.PersonId=Person.PersonId
LEFT JOIN TableTwoItemId ON TableTwoItemId.PersonId=Person.PersonId
WHERE [Person].PersonId=1
GROUP BY Person.[PersonId]

但是这并不认为每个人的计数是分开的,但我总是错误的计数。例如,如果他有1个TableOneItem和2个TableTwoItemIds,则TableOneItemCount为2,而TableTwoItemIdCount为2

4 个答案:

答案 0 :(得分:3)

只需在计数中添加DISTINCT即可:

SELECT Person.[PersonId]

,  Count(DISTINCT TableOneItemId ) as TableOneItemCount
, Count(DISTINCT TableTwoItemIdId ) as TableTwoItemCount
, Count(DISTINCT TableThreeItemId )  as TableThreeItemCount


FROM  [dbo].[Person]
LEFT JOIN TableOneItem ON TableOneItem.PersonId=Person.PersonId
LEFT JOIN TableThreeItemId ON TableThreeItemId.PersonId=Person.PersonId
LEFT JOIN TableTwoItemId ON TableTwoItemId.PersonId=Person.PersonId
WHERE [Person].PersonId=1
GROUP BY Person.[PersonId]

答案 1 :(得分:2)

SELECT Person.[PersonId]

,  (SELECT Count(TableOneItemId ) from TableOneItem where TableOneItem.PersonId=Person.PersonId) as TableOneItemCount
,  (SELECT Count(TableTwoItemId ) from TableTwoItem where TableTwoItem.PersonId=Person.PersonId) as TableTwoItemCount
,  (SELECT Count(TableThreeItemId ) from TableThreeItem where TableThreeItem.PersonId=Person.PersonId) as TableThreeItemCount

FROM  [dbo].[Person]
WHERE [Person].PersonId=1

答案 2 :(得分:2)

您可以使用join

在一个count(distinct)中执行此操作
SELECT Person.[PersonId], 
       Count(distinct TableOneItemId ) as TableOneItemCount,
       Count(distinct TableTwoItemIdId ) as TableTwoItemCount,
       Count(distinct TableThreeItemId )  as TableThreeItemCount
FROM  [dbo].[Person] LEFT JOIN
      TableOneItem
      ON TableOneItem.PersonId = Person.PersonId LEFT JOIN
      TableThreeItemId
      ON TableThreeItemId.PersonId = Person.PersonId LEFT JOIN
      TableTwoItemId
      ON TableTwoItemId.PersonId = Person.PersonId
WHERE [Person].PersonId = 1
GROUP BY Person.[PersonId];

如果您希望计数甚至适度大,则不建议这样做。如果计数均为100,那么这将为每个人生成100 * 100 * 100 = 1,000,000个中间行的笛卡尔积。处理方式太多了。在这种情况下,您希望将计数作为子查询进行。

SELECT Person.[PersonId], TableOneItemCount, TableTwoItemCount, TableThreeItemCount
FROM  [dbo].[Person] LEFT JOIN
      (select personid, count(TableOneItemId) as TableOneItemCount from TableOneItem where PersonId = 1 group by personid
      ) t1
      ON t1.PersonId = Person.PersonId LEFT JOIN
      (select personid, count(TableTwoItemId) as TableTwoItemCount from TableTwoItem where PersonId = 1 group by personid
      ) t2
      ON t2.PersonId = Person.PersonId LEFT JOIN
      (select personid, count(TableThreeItemId) as TableThreeItemCount from TableThreeItem where PersonId = 1 group by personid
      ) t3
      ON t3.PersonId = Person.PersonId
WHERE Person.PersonId = 1;

在大多数情况下,您只需在子查询中使用group by PersonId进行计算,而不使用where。但你只选择了一个人。

答案 3 :(得分:0)

join将为每个组合创建一个行,并且仅在之后应用分组。因此,正如您所指出的,这不会生成正确的输出。一个技巧是在加入之前执行分组和计算

SELECT    Person.[PersonId], TableOneItemCount, TableTwoItemCount, TableThreeItemCount
FROM      Person
LEFT JOIN (SELECT   PersonId, COUNT(*) AS TableOneItemCount
           FROM     TableOneItem
           GROUP BY PersonId) t1 ON p.PersonId = t1.PersonId
LEFT JOIN (SELECT   PersonId, COUNT(*) AS TableTwoItemCount
           FROM     TableTwoItem
           GROUP BY PersonId) t2 ON p.PersonId = t2.PersonId
LEFT JOIN (SELECT   PersonId, COUNT(*) AS TableThreeItemCount
           FROM     TableThreeItem
           GROUP BY PersonId) t3 ON p.PersonId = t3.PersonId
WHERE     [Person].PersonId = 1