SQL Server и эффективность большого диапазона значений в предложении IN - PullRequest
3 голосов
/ 08 марта 2012

У меня есть случай, похожий на этот вопрос MySQL относительно предложения IN, но для SQL Server.

В частности, я строю исполняемую строку SQL, и в ней естьвозможность ОЧЕНЬ длинного списка перечисляемых элементов для использования в предложении IN (IE 1000 +).

Это эффективный способ построения моего фильтра из динамического списка критериев, или я должен вставитьданные критериев во временную таблицу, а затем JOIN это в мою таблицу экспорта для операции фильтрации?

Плюсы и минусы каждого подхода будут оценены, если ответ не совсем прямой.

Я прошу прощения, если этот вопрос был задан.Связанный вопрос MySQL довольно старый.Я полагаю, что это дубликат для SQL Server, но я не могу его найти.

Ответы [ 2 ]

3 голосов
/ 08 марта 2012

Вы забыли сообщить нам, какую версию SQL Server вы используете.Конечно, с каждой новой версией мы получаем возможности, которые помогают нам решать проблемы более эффективным способом.

В SQL Server 2005+ для реализации объединения можно использовать простую табличную функцию, подобную этой:

CREATE FUNCTION [dbo].[SplitInts]
(
   @List       VARCHAR(MAX),
   @Delimiter  CHAR(1)
)
RETURNS TABLE
AS
   RETURN ( SELECT Item FROM ( SELECT Item = x.i.value('(./text())[1]', 'int') FROM 
            ( SELECT [XML] = CONVERT(XML, '<i>' + REPLACE(@List, @Delimiter, '</i><i>') 
              + '</i>').query('.') ) AS a CROSS APPLY [XML].nodes('i') AS x(i)
          ) AS y WHERE Item IS NOT NULL
   );
GO

Теперь перейдите к большому списку и присоединитесь:

CREATE PROCEDURE dbo.GetData
    @List VARCHAR(MAX)
AS
BEGIN
    SET NOCOUNT ON;

    SELECT t.col1, t.col2 --, ...
      FROM dbo.DataTable AS t
      INNER JOIN dbo.SplitInts(@List, ',') AS i
      ON t.ColumnID = i.Item;
END
GO

Это не фантастика (я писал о производительности различных методов здесь , и при значениях ниже 5000 разница невелика), но может работать лучше, чем специальный IN (...huge list...) запрос.

В SQL Server 2008+ можно использовать параметр с табличным значением.Как и выше, вы можете передать DataTable или любую другую структуру из C # в хранимую процедуру и выполнить соединение.Если вы используете 2008 или выше, я могу добавить пример для этого.

1 голос
/ 08 марта 2012

Я предлагаю подход с использованием промежуточной таблицы и использую предложение where exists(...), например,

select * from Employees e
where exists(select 1 from BigEmplCriteriaTable where criteria=e.EmployeeLoc)
...