SQL Server:一个查询中的两个COUNT在输出中相互相乘

时间:2018-03-02 17:03:18

标签: sql sql-server tsql aggregate-functions

我有一个查询用于显示队列中的信息,部分信息显示属于父实体(更改)的子实体(包和实验室)的数量。然而,它们不是显示每种类型儿童的个人数量,而是相互相乘。

在下面的例子中,应该有3个实验室和18个包,但是它们相互相乘,每个输出为54个。

以下是查询的违规部分。

SELECT cef.ChangeId, COUNT(pac.PackageId) AS 'Packages', COUNT(lab.LabRequestId) AS 'Labs'
FROM dbo.ChangeEvaluationForm cef
LEFT JOIN dbo.Lab
ON cef.ChangeId = Lab.ChangeId
LEFT JOIN dbo.Package pac 
ON (cef.ChangeId = pac.ChangeId AND pac.PackageStatus != 6 AND pac.PackageStatus !=7)
WHERE cef.ChangeId = 255
GROUP BY cef.ChangeId

我觉得这很明显,但我没有想到如何修复它,所以两个计数彼此独立,就像我应该这样。在我的任何研究中似乎都没有这样的场景。任何人都可以指导我朝正确的方向发展吗?

3 个答案:

答案 0 :(得分:2)

因为您通过每个左连接将源行相乘。所以有时候你更有可能cross join

SELECT cef.ChangeId, p.Packages, l.Labs
FROM dbo.ChangeEvaluationForm cef
OUTER APPLY(
  SELECT COUNT(*) as Labs
  FROM dbo.Lab
  WHERE cef.ChangeId = Lab.ChangeId
) l
OUTER APPLY(
  SELECT COUNT(*) AS Packages
  FROM dbo.Package pac 
  WHERE (cef.ChangeId = pac.ChangeId AND pac.PackageStatus != 6 AND pac.PackageStatus !=7)
) p
WHERE cef.ChangeId = 255
GROUP BY cef.ChangeId

现在可能不需要GROUP BY

答案 1 :(得分:1)

从您的问题来看,很难得出您对查询的期望结果。所以我认为你想要以下结果:

+----------+----------+------+
| ChangeId | Packages | Labs |
+----------+----------+------+
|      255 |       18 |    3 |
+----------+----------+------+

如果您正在寻找上述结果,请尝试以下查询。

SELECT cef.ChangeId, ISNULL(pac.PacCount, 0) AS 'Packages', ISNULL(Lab.LabCount, 0) AS 'Labs'
FROM dbo.ChangeEvaluationForm cef
LEFT JOIN (SELECT Lab.ChangeId, COUNT(*) LabCount FROM dbo.Lab GROUP BY) Lab
ON cef.ChangeId = Lab.ChangeId
LEFT JOIN (SELECT pac.ChangeId, COUNT(*) PacCount FROM dbo.Package pac WHERE pac.PackageStatus != 6 AND pac.PackageStatus !=7 GROUP BY pac.ChangeId) pac
ON cef.ChangeId = pac.ChangeId
WHERE cef.ChangeId = 255

查询说明:

  • 在你的查询中,你没有使用group by,所以它最终给你54作为笛卡尔积的计数。
  • 在此查询中,我尝试按' ChangeId'进行分组。并在连接表之前查找聚合。因此,加入前将计算3个实验室和18个包。
  • 您还会注意到我已经在PackageStatus表格中移动了pac过滤器。因此,不受欢迎的记录不会让我们的计数变得混乱。

答案 2 :(得分:0)

您从dbo.ChangeEvaluationForm表(您的示例中的ChangeId = 255)开始使用特定的ChangeId,然后加入dbo.Lab表。这个连接使得你的结果从1行变为3,考虑到有3个Labs,其中ChangeId = 255.你的问题是在下一个连接中,你将使用dbo.Package表加入前一个连接的所有3个结果行, ChangeId = 255的18行。对于pac.PackageId和lab.LabRequestId列的结果计数将是3 x 18 = 54。

为了得到你想要的东西,有两个简单的解决方案:

  • 使用COUNT DISTINCT代替COUNT。这将只计算pac.PackageId和lab.LabRequestId的不同值,而不是重复的值。
  • 将联接拆分为2个子查询并加入其结果(通过ChangeId)