Today I was diving into some extremely wide tables, I wanted to take a quick look at things like “How many unique values does this table have in every column?”.
This can be super useful if you have a spreadsheet of results or a schema without effective normalization and you want to determine which rows are the “most unique” – or have high cardinality.
The Github gist is embedded at the bottom of the page, but I will run you through the code in case you want an explanation of how it works
The procedure takes a schema and a table/view name and combines them – I could ask the user to do this for me, but there’s parts where its useful to break them up and I dont want to mess with split logic :p

The procedure is defined as a temporary stored procedure as I didnt want to leave a trace when I disconnect.
I then define the dynamic UNPIVOT statement, which we will feed our dynamic column listing from.

Gather our columns (twice) – once for the COUNT(DISTINCT), and once for the use in the columns we want to UNPIVOT.

Here’s an example of running it against a tsqlt testresult table:

As we can see, the tsqlt testresult table has one class, two messages and results, and unique everything else (so that’s where I will focus.)
I also utilize a @magic_value variable in the code (not shown) which I use to deal with the fact that a NULL value in an UNPIVOT statement wont count as an occurrence. I want to disambiguate from NULL and any particular value that might occur, so using something like -1 or some string NULL would be inappropriate.
That’s it for today!
Grab the full code below –
CREATE OR ALTER procedure #data_sampler | |
( | |
@schema_name NVARCHAR(128) = 'dbo', | |
@object_name NVARCHAR(128) | |
) | |
AS | |
BEGIN | |
SET NOCOUNT ON; | |
DECLARE | |
@SQL NVARCHAR(MAX) = | |
' | |
SELECT * | |
FROM | |
( | |
SELECT | |
/*column_list_with_distinct*/ | |
FROM ' + QUOTENAME(@schema_name) + '.' + QUOTENAME(@object_name)+' AS t | |
) AS summary | |
UNPIVOT | |
( | |
row_count | |
FOR | |
table_name IN | |
( | |
/*column_list*/ | |
) | |
) AS unp | |
ORDER BY | |
row_count DESC | |
', | |
@column_list_with_distinct NVARCHAR(MAX), | |
@column_list NVARCHAR(MAX), | |
@magic_value NVARCHAR(73) = '39EACB36-3C89-4E6B-A488-15F8F7E5D363-9CC5643D-8F87-422D-BA48-34A28029CE7B' | |
SELECT | |
@column_list_with_distinct = | |
STRING_AGG | |
( | |
CONVERT | |
( | |
NVARCHAR(MAX), | |
CONCAT | |
( | |
'COUNT(DISTINCT CASE WHEN ', | |
QUOTENAME(c.name), | |
' IS NULL THEN @magic_value ELSE CONVERT(VARCHAR(MAX),', | |
QUOTENAME(c.name), | |
') END ) AS ', | |
QUOTENAME(c.name) | |
) | |
), | |
CONCAT | |
( | |
',', | |
CHAR(10), | |
CHAR(9), | |
CHAR(9) | |
) | |
), | |
@column_list = | |
STRING_AGG(QUOTENAME(c.name), ',') | |
FROM sys.objects AS so | |
JOIN sys.schemas AS s ON | |
s.schema_id = so.schema_id | |
JOIN sys.columns AS c ON | |
so.object_id = c.object_id | |
WHERE | |
so.name = @object_name | |
AND s.name = @schema_name | |
END | |
SET @SQL = REPLACE(REPLACE(@SQL,'/*column_list_with_distinct*/',@column_list_with_distinct),'/*column_list*/',@column_list) | |
EXEC sp_executesql @SQL, N'@magic_value NVARCHAR(73)', @magic_value = @magic_value | |
GO |