如何改进下面的SQL查询(SQL Server 2008)?我想尝试避免子选择,我正在使用它们中的一些产生这样的结果
StateId TotalCount SFRCount OtherCount
---------------------------------------------------------
AZ 102 50 52
CA 2931 2750 181
etc...
SELECT
StateId,
COUNT(*) AS TotalCount,
(SELECT COUNT(*) AS Expr1 FROM Property AS P2
WHERE (PropertyTypeId = 1) AND (StateId = P.StateId)) AS SFRCount,
(SELECT COUNT(*) AS Expr1 FROM Property AS P3
WHERE (PropertyTypeId <> 1) AND (StateId = P.StateId)) AS OtherCount
FROM Property AS P
GROUP BY StateId
HAVING (COUNT(*) > 99)
ORDER BY StateId
答案 0 :(得分:10)
这可能会有相同的效果,很难在没有数据的情况下进行测试
SELECT
StateId,
COUNT(*) AS TotalCount,
SUM(CASE WHEN PropertyTypeId = 1 THEN 1 ELSE 0 END) as SFRCount,
SUM(CASE WHEN PropertyTypeId <> 1 THEN 1 ELSE 0 END) as OtherCount
FROM Property AS P
GROUP BY StateId
HAVING (COUNT(*) > 99)
ORDER BY StateId
答案 1 :(得分:0)
您的替代选择是Property
使用WHERE
条件作为加入参数的单个自加入。可以通过在派生查询中减去TotalCount - SFRCount
来派生OtherCount。
答案 2 :(得分:0)
另一种选择是使用像这样的PIVOT函数:
SELECT StateID, [1] + [2] AS TotalCount, [1] AS SFRCount, [2] AS OtherCount
FROM Property
PIVOT ( COUNT(PropertyTypeID)
FOR PropertyTypeID IN ([1],[2])
) AS pvt
WHERE [1] + [2] > 99
您需要为每种属性类型添加一个可能令人生畏的条目,但这是另一种选择。斯科特有一个很好的答案。
答案 3 :(得分:0)
如果PropertyTypeId不为null,那么您可以使用单个连接执行此操作。计数比总和快。但是Count加入比Sum更快。下面的测试用例模仿您的数据。 docSVsys有800,000行,caseID有大约300个唯一值。此测试用例中的Count加入稍微快于Sum。但是如果我删除with(nolock)那么Sum大约快1/4。您需要使用您的数据进行测试。
select GETDATE()
go;
select caseID, COUNT(*) as Ttl,
SUM(CASE WHEN mimeType = 'message/rfc822' THEN 1 ELSE 0 END) as SFRCount,
SUM(CASE WHEN mimeType <> 'message/rfc822' THEN 1 ELSE 0 END) as OtherCount,
COUNT(*) - SUM(CASE WHEN mimeType = 'message/rfc822' THEN 1 ELSE 0 END) as OtherCount2
from docSVsys with (nolock)
group by caseID
having COUNT(*) > 1000
select GETDATE()
go;
select docSVsys.caseID, COUNT(*) as Ttl
, COUNT(primaryCount.sID) as priCount
, COUNT(*) - COUNT(primaryCount.sID) as otherCount
from docSVsys with (nolock)
left outer join docSVsys as primaryCount with (nolock)
on primaryCount.sID = docSVsys.sID
and primaryCount.mimeType = 'message/rfc822'
group by docSVsys.caseID
having COUNT(*) > 1000
select GETDATE()
go;