Чи COALESCE зараз досяжний?


9

Один з моїх розробників стверджує, що COALESCE(column, default value) = default valueце зараз можна. Це так?

Я провів наступний тест, і я думаю, що це означає, що COALESCEце неможливо.

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 <X64> (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.

5
Чи сперечався ваш розробник з якимись доказами?
Аарон Бертран

Я читаю цей пост: josef-richberg.squarespace.com/journal/2010/1/28/… Я не думаю, що для відповіді на це повідомлення можна отримати конкретну відповідь. (Але, можливо, хтось інший знає краще.)
RLF

@RLF - у цій статті не сказано нічого, що вказувало б на те, що вона є придатною для збору. Це не є демонстрацією того, що він є причетним. twitpic.com/107ms0 . Нездатність полягає в тому, що вона перешкоджає пошуку стовпців, що використовуються у CASEвиразі, - не те, що результат виразу не може бути використаний для пошуку чогось іншого.
Мартін Сміт

@AaronBertrand, "План виконання виглядав однаково, як би я його не писав" - Він ігнорував той факт, що жоден не здійснював пошук на основі COALESCEколонки d.
Мітч

1
О, я не звинувачую вас у тому, що ви задали це питання, тим більше що ви спробували спростувати його спочатку. Я просто пропонував, що, можливо, ваш розробник повинен навчитися робити те саме.
Аарон Бертран

Відповіді:


15

Ні COALESCEНЕ sargable.

Ваш власний тест це добре демонструє.

Винятком буде, якщо ви створили обчислену колонку з COALESCEвиразом та індексували це.

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;

ISNULL є незначно більш сприятливим у тому, що якщо він є абсолютно зайвим, його можна оптимізувати і не перешкоджати пошуку.

тобто якщо стовпець Mod6визначений як NOT NULLнаступний, наступне може викликати пошук.

SELECT Mod6
FROM Test 
WHERE ISNULL(Mod6, 0) = 0;

Але це, звичайно, не дає ніякої користі, ніж просто робити

WHERE Mod6 = 0
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.