Asp.net

計算列中不同值(包括 NULL 值)的最快方法

  • October 31, 2014

Transact-Sql Count Distinct操作對列中的所有非空值進行計數。我需要計算一組表中每列的不同值的數量,包括空值(因此,如果列中有空值,則結果應該是(Select Count(Distinct COLNAME) From TABLE) + 1.

這將在數據庫中每個表的每一列上重複。包括數百個表,其中一些表超過 1M 行。因為這需要在每一列上完成,所以為每一列添加索引不是一個好的選擇。

這將作為 ASP.net 站點的一部分完成,因此與程式碼邏輯的集成也可以(即:這不必作為一個查詢的一部分完成,但如果可以以良好的性能完成,那麼即使更好的)。

最有效的方法是什麼?


測試後更新

我從一個很好的代表性表格上給出的答案中測試了不同的方法。該表有 320 萬條記錄,幾十列(少數有索引,大多數沒有)。一列有 320 萬個唯一值。其他列的範圍從所有 Null(一個值)到最多 40K 個唯一值。對於每種方法,我進行了四次測試(每次嘗試多次,平均結果):一次 20 列,一次 5 列,1 列有很多值(3.2M)和 1 列有少量值( 167)。以下是結果,按從快到慢的順序排列

  1. 計數/分組切蘭
  2. CountDistinct+SubQuery (埃利斯)
  3. 密集排名埃里克森
  4. 計數+最大值安德烈

測試結果(以秒為單位):

  Method          20_Columns   5_Columns   1_Column (Large)   1_Column (Small)
1) Count/GroupBy      10.8          4.8            2.8               0.14       
2) CountDistinct      12.4          4.8            3                 0.7         
3) dense_rank        226           30              6                 4.33 
4) Count+Max          98.5         44             16                12.5        

筆記:

  • 有趣的是,最快的兩種方法(到目前為止,兩者之間只有很小的差異)都是為每一列送出單獨查詢的方法(在結果 #2 的情況下,查詢包括一個子查詢,所以有實際上是每列送出兩個查詢)。可能是因為與記憶體需求方面的性能損失相比,通過限製表掃描次數獲得的收益很小(只是猜測)。
  • 雖然 dense_rank 方法絕對是最優雅的,但它似乎並不能很好地擴展(見 20 列的結果,這是迄今為止四種方法中最差的),即使在小規模上也無法與的表現Count

感謝您的幫助和建議!

SELECT COUNT(*)
FROM (SELECT ColumnName
     FROM TableName
     GROUP BY ColumnName) AS s;

GROUP BY選擇不同的值,包括 NULL。 COUNT(*)將包括 NULL,而不是COUNT(ColumnName)忽略 NULL。

OP自己的解決方案的發展:

SELECT
 COUNT(DISTINCT acolumn) + MAX(CASE WHEN acolumn IS NULL THEN 1 ELSE 0 END)
FROM atable

引用自:https://stackoverflow.com/questions/7376564