请考虑以下事项:
IF OBJECT_ID ('tempdb..#Customer') IS NOT NULL
DROP TABLE #Customer;
CREATE TABLE #Customer
(
CustomerKey INT IDENTITY (1, 1) NOT NULL
,CustomerNum INT NOT NULL
,CustomerName VARCHAR (25) NOT NULL
,Planet VARCHAR (25) NOT NULL
)
GO
INSERT INTO #Customer (CustomerNum, CustomerName, Planet)
VALUES (1, 'Anakin Skywalker', 'Tatooine')
, (2, 'Yoda', 'Coruscant')
, (3, 'Obi-Wan Kenobi', 'Coruscant')
, (4, 'Luke Skywalker', 'Tatooine')
, (4, 'Luke Skywalker', 'Tatooine')
, (4, 'Luke Skywalker', 'Bespin')
, (4, 'Luke Skywalker', 'Bespin')
, (4, 'Luke Skywalker', 'Endor')
, (4, 'Luke Skywalker', 'Tatooine')
, (4, 'Luke Skywalker', 'Kashyyyk');
请注意,共有10条记录。我知道我可以获得CustomerName和PLanet的不同组合列表,其中包含以下两个查询之一。
SELECT DISTINCT CustomerName, Planet FROM #Customer;
SELECT CustomerName, Planet FROM #Customer
GROUP BY CustomerName, Planet;
但是,我想要的是一种简单的方法来获取这些值的计数,而不是值本身。我想要一种快速输入的方式,但也有高效的方式。我知道我可以将值加载到CTE,临时表,表变量或子查询中,然后计算记录。有没有更好的方法来实现这一目标?
答案 0 :(得分:6)
这将在2005年有效:
SELECT COUNT(*) AS cnt
FROM
( SELECT 1 AS d
FROM Customer
GROUP BY Customername, Planet
) AS t ;
在 SQL-Fiddle 中进行测试。将使用(CustomerName, Planet)
上的索引,请参阅查询计划(2012版):
最简单的思考,“在子查询中获取所有不同的值,然后计算”,yiields采用相同的相同计划:
SELECT COUNT(*) AS cnt
FROM
( SELECT DISTINCT Customername, Planet
FROM Customer
) AS t ;
还有一个(使用@Aaron Bertrand)使用排名函数ROW_NUMBER()
(不确定它是否在2005版本中也有效,但你可以测试):
SELECT COUNT(*) AS cnt
FROM
(SELECT rn = ROW_NUMBER()
OVER (PARTITION BY CustomerName, Planet
ORDER BY CustomerName)
FROM Customer) AS x
WHERE rn = 1 ;
还有其他方法可以写这个(即使没有子查询,也就是@Mikael Erksson!),但效率不高。
答案 1 :(得分:2)
子查询/ CTE方法是“正确”的方法。
快速(在打字但不一定是性能方面)和肮脏的方式是:
select count(distinct customername+'###'+Planet)
from #Customer;
'###'
用于分隔值,这样就不会发生意外碰撞。