检索计数 - LEFT JOIN VS SELECT COUNT

时间:2017-03-15 00:20:05

标签: sql sql-server select count left-join

我有一种情况,我有两条可能的路线下来,如果有人可以帮助我决定哪一条更好,为什么我会徘徊。我试图查看执行计划,但我不知道哪一个更有效。

所以我需要做的是从一个表中获取每个类型的计数。换句话说,下面的查询试图做什么。

SELECT 
    ObjectId, TypeACount, TypeBCount, TypeCCount
FROM 
    Object 
LEFT JOIN 
    (SELECT ObjectId, COUNT(ObjectId) AS TypeACount FROM ObjectAssociatedData WHERE Type = 'TypeA' GROUP BY ObjectId) AS TypeA
ON
    TypeA.ObjectId = Object.ObjectId
LEFT JOIN 
    (SELECT ObjectId, COUNT(ObjectId) AS TypeBCount FROM ObjectAssociatedData WHERE Type = 'TypeB' GROUP BY ObjectId) AS TypeB
ON
    TypeB.ObjectId = Object.ObjectId    
LEFT JOIN 
    (SELECT ObjectId, COUNT(ObjectId) AS TypeCCount FROM ObjectAssociatedData WHERE Type = 'TypeC' GROUP BY ObjectId) AS TypeC
ON
    TypeC.ObjectId = Object.ObjectId

SELECT 
    ObjectId, 
    (SELECT COUNT(ObjectId) FROM ObjectAssociatedData WHERE Type = 'TypeA' AND ObjectAssociatedData.ObjectId = Object.ObjectId) AS TypeACount,
    (SELECT COUNT(ObjectId) FROM ObjectAssociatedData WHERE Type = 'TypeB' AND ObjectAssociatedData.ObjectId = Object.ObjectId) AS TypeBCount,
    (SELECT COUNT(ObjectId) FROM ObjectAssociatedData WHERE Type = 'TypeC' AND ObjectAssociatedData.ObjectId = Object.ObjectId) AS TypeCCount
FROM 
    Object 

这两个查询都给了我想要的数据,虽然第一个给我NULL,第二个给我0时没有关联值,不关心那个,因为我可以处理它?
我的问题更多的是我应该使用哪一个以及为什么。
正如我之前提到的,我已经看过执行计划,但我不确定如何从那里破译哪一个可能更高性能:(

2 个答案:

答案 0 :(得分:1)

我会改用条件聚合。

select 
    o.ObjectId
  , TypeACount = count(case when oad.Type='TypeA' then 1 end)
  , TypeBCount = count(case when oad.Type='TypeB' then 1 end)
  , TypeCCount = count(case when oad.Type='TypeA' then 1 end)
from [Object] o
  left join ObjectAssociatedData oad
    on oad.ObjectId = o.ObjectId
group by o.ObjectId

select 
    o.ObjectId
  , TypeACount = sum(case when oad.Type='TypeA' then 1 else 0 end)
  , TypeBCount = sum(case when oad.Type='TypeB' then 1 else 0 end)
  , TypeCCount = sum(case when oad.Type='TypeA' then 1 else 0 end)
from [Object] o
  left join ObjectAssociatedData oad
    on oad.ObjectId = o.ObjectId
group by o.ObjectId

答案 1 :(得分:1)

都不是。您应该使用条件聚合:

SELECT o.ObjectId, 
       SUM(CASE WHEN oad.Type = 'TypeA' THEN 1 ELSE 0 END) AS TypeACount,
       SUM(CASE WHEN oad.Type = 'TypeB' THEN 1 ELSE 0 END) AS TypeBCount,
       SUM(CASE WHEN oad.Type = 'TypeC' THEN 1 ELSE 0 END) AS TypeCCount
FROM Object o LEFT JOIN
     ObjectAssociatedData oad
     ON oad.ObjectId = o.ObjectId
GROUP BY o.ObjectId;

如果ObjectAssociatedData除了这三种类型之外还有类型,那么您可能需要添加WHERE子句:

WHERE oad.Type IN ('TypeA', 'TypeB', 'TypeC')