1

请考虑以下几点:

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、临时表、表变量或子查询中,然后对记录进行计数。有没有更好的方法来实现这一点?

4

2 回答 2

6

这将在 2005 年生效:

SELECT COUNT(*) AS cnt
FROM
 ( SELECT 1 AS d
   FROM  Customer
   GROUP BY Customername, Planet
 ) AS t ;

SQL-Fiddle中测试。将使用索引(CustomerName, Planet),请参阅查询计划(适用于 2012 版):

查询计划

最简单的想法是“在子查询中获取所有不同的值,然后计数”,产生相同的相同计划:

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!)但效率不高。

于 2013-06-07T15:23:55.470 回答
2

子查询/CTE 方法是执行此操作的“正确”方法。

一种快速(就打字但不一定是性能而言)和肮脏的方式是:

select count(distinct customername+'###'+Planet)
from #Customer;

'###'是为了将值分开,以免发生意外碰撞。

于 2013-06-07T13:26:48.957 回答