patternsqlModerate
Is COALESCE sargable now?
Viewed 0 times
nowsargablecoalesce
Problem
One of my developers is arguing that
I ran the following test, and think it implies that
COALESCE(column, default value) = default value is now sargable. Is that right?I ran the following test, and think it implies that
COALESCE is non-sargable.USE tempdb;
SELECT @@VERSION;
-- Microsoft SQL Server 2016 (RTM-CU3-GDR) (KB3194717) - 13.0.2186.6 (X64) Oct 31 2016 18:27:32 Copyright (c) Microsoft Corporation Developer Edition (64-bit) on Windows 10 Pro 6.3 (Build 14393: ) (Hypervisor)
CREATE TABLE Test
(
ID int primary key clustered,
Mod6 int null,
INDEX IX_Mod6 NONCLUSTERED (Mod6)
);
INSERT INTO Test (ID, Mod6)
SELECT object_id as ID, case when name like '%k%' then null else object_id % 6 end as Mod6
FROM sys.objects;
SELECT Mod6
FROM Test WITH (INDEX = IX_Mod6, FORCESEEK)
where Mod6 is null or Mod6 = 0;
-- Plan shows expected seek
SELECT Mod6
FROM Test WITH (INDEX = IX_Mod6, FORCESEEK)
WHERE COALESCE(Mod6, 0) = 0;
-- Error:
-- Msg 8622, Level 16, State 1, Line 20
-- Query processor could not produce a query plan because of the hints
-- defined in this query. Resubmit the query without specifying any hints
-- and without using SET FORCEPLAN.Solution
No
Your own test demonstrates this well.
An exception would be if you created a computed column with the
You could end up with a seek on that
i.e. if the column
But this of course doesn't supply any benefit over just doing
COALESCE is not sargable.Your own test demonstrates this well.
An exception would be if you created a computed column with the
COALESCE expression and indexed that.CREATE TABLE Test
(
ID int primary key clustered,
Mod6 int null,
Foo AS COALESCE(Mod6, 0),
INDEX IX_Mod6 NONCLUSTERED (Mod6),
INDEX IX2_Mod6 NONCLUSTERED (Foo),
);You could end up with a seek on that
SELECT Mod6
FROM Test WITH (INDEX = IX2_Mod6, FORCESEEK)
WHERE COALESCE(Mod6, 0) = 0;ISNULL is marginally more sargable in that if it is totally redundant it can be optimised out and not prevent a seek.i.e. if the column
Mod6 is defined as NOT NULL then the following can produce a seek.SELECT Mod6
FROM Test
WHERE ISNULL(Mod6, 0) = 0;But this of course doesn't supply any benefit over just doing
WHERE Mod6 = 0Code Snippets
CREATE TABLE Test
(
ID int primary key clustered,
Mod6 int null,
Foo AS COALESCE(Mod6, 0),
INDEX IX_Mod6 NONCLUSTERED (Mod6),
INDEX IX2_Mod6 NONCLUSTERED (Foo),
);SELECT Mod6
FROM Test WITH (INDEX = IX2_Mod6, FORCESEEK)
WHERE COALESCE(Mod6, 0) = 0;SELECT Mod6
FROM Test
WHERE ISNULL(Mod6, 0) = 0;WHERE Mod6 = 0Context
StackExchange Database Administrators Q#162024, answer score: 15
Revisions (0)
No revisions yet.