2015-01-10 94 views
2

我有三个表格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

+0

你能在你的表中添加样本数据和你所期望的输出? – SMA

回答

2

您可以通过使用count(distinct)单一join做到这一点:

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计算。但你只选择一个人。

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 
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] 
0

join ING会为每种组合创建一个行,分组将只应用之后。所以,如你所说,这不会产生正确的输出。一个技巧就是你加入之前进行分组和计数

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 
+0

您在连接条件中的PeronsId上进行了有效筛选..您不需要“按组”进行分组。另外,您应该考虑外部选择中的空值。即。 'SELECT Person。[PersonId],COALESCE(TableOneItemCount,0)TableOneItemCount,COALESCE(TableTwoItemCount,0)TableTwoItemCount,COALESCE(TableThreeItemCount,0)TableThreeItemCount' –