Фильтрация с несколькими полями выбора с SQL Server - PullRequest
2 голосов
/ 05 января 2009

Мне нужно отфильтровать наборы результатов с сервера SQL на основе выбора из списка со множественным выбором. Мне пришла в голову идея создания экземпляра, чтобы определить, существует ли значение строки в выбранных значениях фильтра, но это склонно к частичному соответствию (например, Car соответствует Carpet).

Я также прошел разделение строки на таблицу и соединение / сопоставление, основываясь на этом, но у меня есть сомнения относительно того, как это будет выполняться.

Поскольку это, казалось бы, обычная задача, я обращаюсь к сообществу Stack Overflow за некоторыми отзывами и, возможно, парой предложений относительно наиболее часто используемого подхода к решению этой проблемы.

Ответы [ 3 ]

4 голосов
/ 05 января 2009

Я решил эту проблему, написав табличную функцию (мы используем 2005), которая принимает строку с разделителями и возвращает таблицу. Затем вы можете присоединиться к этому или использовать WHERE EXISTS или WHERE x IN. Мы еще не провели полное стресс-тестирование, но при ограниченном использовании и достаточно небольших наборах элементов я считаю, что производительность должна быть в порядке.

Ниже приведена одна из функций для вас. У меня также есть один, написанный специально для принятия списка INT с разделителями для значений ID в таблицах поиска и т. Д.

Другая возможность - использовать LIKE с разделителями, чтобы убедиться, что частичные совпадения игнорируются, но вы не можете использовать индексы с этим, поэтому производительность будет низкой для любой большой таблицы. Например:

SELECT
     my_column
FROM
     My_Table
WHERE
     @my_string LIKE '%|' + my_column + '|%'

.

/*
    Name:       GetTableFromStringList
    Description:    Returns a table of values extracted from a delimited list
    Parameters:
            @StringList - A delimited list of strings
            @Delimiter - The delimiter used in the delimited list

    History:
    Date        Name            Comments
    ----------  -------------   ----------------------------------------------------
    2008-12-03  T. Hummel   Initial Creation
*/
CREATE FUNCTION dbo.GetTableFromStringList
(
    @StringList VARCHAR(1000),
    @Delimiter  CHAR(1) = ','
)
RETURNS @Results TABLE
(
    String  VARCHAR(1000)   NOT NULL
)
AS
BEGIN
    DECLARE
        @string     VARCHAR(1000),
        @position   SMALLINT

    SET @StringList = LTRIM(RTRIM(@StringList)) + @Delimiter
    SET @position = CHARINDEX(@Delimiter, @StringList)

    WHILE (@position > 0)
    BEGIN
        SET @string = LTRIM(RTRIM(LEFT(@StringList, @position - 1)))

        IF (@string <> '')
        BEGIN
            INSERT INTO @Results (String) VALUES (@string)
        END

        SET @StringList = RIGHT(@StringList, LEN(@StringList) - @position)
        SET @position = CHARINDEX(@Delimiter, @StringList, 1)
    END

    RETURN
END
1 голос
/ 05 января 2009

У меня была идея сделать instring, чтобы определить, является ли значение строки существует в выбранных значениях фильтра, но это склонно к частичным совпадениям (например, автомобиль соответствует Carpet)

Мне кажется, что вы не указали уникальный идентификатор или, возможно, первичный ключ как часть значений в вашем списке. В идеале каждый параметр должен иметь уникальный идентификатор, соответствующий столбцу в таблице, по которой вы ищете. Если бы ваш список был похож на ниже, вы могли бы фильтровать специально для автомобилей, потому что вы получите уникальное значение 3.

<option value="3">Car</option>
<option value="4">Carpret</option>

Затем вы просто создаете предложение where, которое позволит вам найти нужные значения.


Обновлено, чтобы ответить на комментарий.

Как бы я сделал связанное соединение учитывая, что пользователь может выбрать и произвольное количество вариантов из список? ВЫБРАТЬ * ИЗ ТАБЛИЦЫ ПРИСОЕДИНЯЙТЕСЬ к tblOptions ON tblTable.FK =? Проблема в том, что мне нужно присоединиться к несколько значений.

Я ответил на аналогичный вопрос здесь .

Одним из методов будет создание временной таблицы и добавление каждого выбранного параметра в виде строки во временную таблицу. Тогда вы просто присоединитесь к вашей временной таблице.

Если вы хотите просто создать свой sql динамически, вы можете сделать что-то вроде этого.

SELECT * FROM tblTable WHERE option IN (selected_option_1, selected_option_2, selected_option_n)
0 голосов
/ 06 января 2009

Я обнаружил, что таблично-значная функция CLR, которая принимает строку с разделителями и вызывает строку Split (возвращая массив как IEnumerable), является более производительной, чем все, что написано в T-SQL (она начинает ломаться, когда у вас есть около миллиона элементов в списке с разделителями, но это намного дальше, чем решение T-SQL).

И тогда вы можете присоединиться к столу или проверить с помощью EXISTS.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...