我有以下SQL:
SELECT j.AssocJobKey
, COUNT(DISTINCT o.ID) AS SubjectsOrdered
, COUNT(DISTINCT s.ID) AS SubjectsShot
FROM Jobs j
LEFT JOIN Orders o ON o.AssocJobKey = j.AssocJobKey
LEFT JOIN Subjects s ON j.AssocJobKey = s.AssocJobKey
GROUP BY
j.AssocJobKey
,j.JobYear
基本结构是Job,是AssocJobKey唯一的父项,并且与Subjects和Orders具有一对多的关系。 该查询提供了我想要的内容,输出如下所示:
| AssocJobKey | SubjectsOrdered | SubjectsShot |
|-----------------------|------------------------|---------------------|
| BAT-H181 | 107 | 830 |
|--------------------- |------------------------|---------------------|
| BAT-H131 | 226 | 1287 |
问题在于查询很繁琐,而我的存储量却增加了,无法在大型数据集上运行它。如果我删除了对应计数中的LEFT JOIN之一,查询将立即执行并且没有问题。因此,某种程度上,两个左联接之间的反弹比它们应有的多,但我不明白为什么会这样。
真的希望尽可能避免加入子选择。
答案 0 :(得分:1)
您的查询正在为每个作业生成笛卡尔积。这是很大的-您的第二行产生了约50万行。 COUNT(DISTINCT)
然后必须找出该笛卡尔积中的唯一ID。
解决方案很简单:预先汇总:
SELECT j.AssocJobKey, o.SubjectsOrdered, s.SubjectsShot
FROM Jobs j LEFT JOIN
(SELECT o.AssocJobKey, COUNT(*) as SubjectsOrdered
FROM Orders o
GROUP BY o.AssocJobKey
) o
ON o.AssocJobKey = j.AssocJobKey LEFT JOIN
(SELECT j.AssocJobKey, COUNT(s.ID) AS SubjectsShot
FROM Subjects s
GROUP BY j.AssocJobKey
) s
ON j.AssocJobKey = s.AssocJobKey;
这做出了一些我认为合理的假设:
id
是唯一的且非NULL。jobs.AssocJobKey
是唯一的。如果其中任何一个都不正确,则可以轻松地调整查询,但它们似乎是合理的假设。
通常对于不同维度上的这些类型的联接,COUNT(DISTINCT)
是一个合理的解决方案(查询当然更简单)。当最多只有几个值时,这是正确的。