Dold pärla i SQL språket hjälper oss att jämföra dataset

Oopps! Upgrade your browser pretty please. Oopps! Upgrade your browser pretty please.

Att SQL språket är rikt vet ju de flesta av oss som håller på med det dagligen. Dock använder man ofta samma sätt och kanske inte tar till sig alla nyheter eller förbättringar som kommer med varje version och uppdateringar.

En av dessa är EXCEPT som faktiskt kan användas i alla SQL Server versioner efter SQL Server 2005 och som inte är så känd.
Med den kan man enkelt jämföra två dataset, exempelvis ta reda på antal nya rader och jämföra skillnader mellan två frågors resultat-set. Man kan skapa audittabeller och massor med annat.
Det som är så bra med den är den enkla syntax’en som är just EXCEPT. Det krävs bara samma antal kolumner med samma datatyper. Prestandan är också helt ok.
Nedan följer ett exempel som räknar antal rader i en databas, väntar 10 sekunder, räknar antal rader igen och jämför sedan detta med just EXCEPT. Hur användbart som helst.

-- Count no of rows
SELECT QUOTENAME(SCHEMA_NAME(sOBJ.schema_id)) + '.' + QUOTENAME(sOBJ.name) AS TableName ,
SUM(sdmvPTNS.row_count) AS NoOfRows
INTO #tmp1
FROM sys.objects AS sOBJ
INNER JOIN sys.dm_db_partition_stats AS sdmvPTNS ON sOBJ.object_id = sdmvPTNS.object_id
WHERE sOBJ.type = 'U'
AND sOBJ.is_ms_shipped = 0x0
AND sdmvPTNS.index_id < 2
GROUP BY sOBJ.schema_id ,
sOBJ.name

-- Wait 10 seconds
WAITFOR DELAY '00:00:10';

-- Count no of rows
SELECT QUOTENAME(SCHEMA_NAME(sOBJ.schema_id)) + '.' + QUOTENAME(sOBJ.name) AS TableName ,
SUM(sdmvPTNS.row_count) AS NoOfRows
INTO #tmp2
FROM sys.objects AS sOBJ
INNER JOIN sys.dm_db_partition_stats AS sdmvPTNS ON sOBJ.object_id = sdmvPTNS.object_id
WHERE sOBJ.type = 'U'
AND sOBJ.is_ms_shipped = 0x0
AND sdmvPTNS.index_id < 2
GROUP BY sOBJ.schema_id ,
sOBJ.name

-- Except
SELECT *
INTO #tmp3
FROM #tmp1
EXCEPT
SELECT *
FROM #tmp2

-- Result
SELECT #tmp3.TableName ,
#tmp3.NoOfRows ,
tmp2.NoOfRows ,
ISNULL(tmp2.NoOfRows, 0) - #tmp3.NoOfRows AS DiffNoOfRows
FROM #tmp3
OUTER APPLY ( SELECT #tmp2.NoOfRows
FROM #tmp2
WHERE #tmp2.TableName = #tmp3.TableName
) tmp2

DROP TABLE #tmp1
DROP TABLE #tmp2
DROP TABLE #tmp3