【问题标题】:Getting Count Only of Distinct Value Combinations of multiple fields.仅获取多个字段的不同值组合的计数。
【发布时间】:2013-06-07 13:21:57
【问题描述】:

请考虑以下几点:

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

【问题讨论】:

  • 为什么“快速打字”是一项要求?您多久手动编写一次这些查询?你能告诉我们什么更重要:查询是高效的,还是查询“快速输入”?
  • 我已向@ypercube's SQLFiddle 添加了一些其他查询变体。您应该对其进行测试,然后可以根据性能和/或打字手指的压力来决定您最喜欢哪一个。

标签: sql sql-server tsql sql-server-2005 sql-server-2012


【解决方案1】:

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

【讨论】:

  • 在更新后的SQL Fiddle 中增加了两种给猫剥皮的方法。
【解决方案2】:

子查询/CTE 方法是“正确”的方法。

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

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

'###' 用于分隔值,以免发生意外碰撞。

【讨论】:

  • 虽然性能很差。而且您还必须确保# 不能自然地出现在您的数据中,
  • @AaronBertrand 。 . . OP 明确表示不要使用 CTE/子查询等:“我知道我可以将值加载到 CTE、临时表、表变量或子查询中,然后计算记录。”你能想到另一种方法吗?
  • 我意识到这一点。我的评论不仅适用于 OP(他还表示“性能” - 而不是一个词 - 是一项要求)。您的答案说“一种快速而肮脏的方式”,这可能会让人们相信它的性能与子查询相同,甚至可能更好。您应该包含一个免责声明,它实际上会比子查询/CTE 方法慢。 我认为不使用子查询/CTE 的要求无论如何都是人为的。
猜你喜欢
  • 2020-12-29
  • 1970-01-01
  • 1970-01-01
  • 2023-04-08
  • 1970-01-01
  • 2021-09-17
  • 2014-07-02
  • 1970-01-01
  • 2015-05-15
相关资源
最近更新 更多