Counting DISTINCT over multiple columns Counting DISTINCT over multiple columns sql-server sql-server

Counting DISTINCT over multiple columns


If you are trying to improve performance, you could try creating a persisted computed column on either a hash or concatenated value of the two columns.

Once it is persisted, provided the column is deterministic and you are using "sane" database settings, it can be indexed and / or statistics can be created on it.

I believe a distinct count of the computed column would be equivalent to your query.


Edit: Altered from the less-than-reliable checksum-only queryI've discovered a way to do this (in SQL Server 2005) that works pretty well for me and I can use as many columns as I need (by adding them to the CHECKSUM() function). The REVERSE() function turns the ints into varchars to make the distinct more reliable

SELECT COUNT(DISTINCT (CHECKSUM(DocumentId,DocumentSessionId)) + CHECKSUM(REVERSE(DocumentId),REVERSE(DocumentSessionId)) )FROM DocumentOutPutItems


What is it about your existing query that you don't like? If you are concerned that DISTINCT across two columns does not return just the unique permutations why not try it?

It certainly works as you might expect in Oracle.

SQL> select distinct deptno, job from emp  2  order by deptno, job  3  /    DEPTNO JOB---------- ---------        10 CLERK        10 MANAGER        10 PRESIDENT        20 ANALYST        20 CLERK        20 MANAGER        30 CLERK        30 MANAGER        30 SALESMAN9 rows selected.SQL> select count(*) from (  2  select distinct deptno, job from emp  3  )  4  /  COUNT(*)----------         9SQL>

edit

I went down a blind alley with analytics but the answer was depressingly obvious...

SQL> select count(distinct concat(deptno,job)) from emp  2  /COUNT(DISTINCTCONCAT(DEPTNO,JOB))---------------------------------                                9SQL>

edit 2

Given the following data the concatenating solution provided above will miscount:

col1  col2----  ----A     AAAA    A

So we to include a separator...

select col1 + '*' + col2 from t23/

Obviously the chosen separator must be a character, or set of characters, which can never appear in either column.