Фильтрация с помощью полей множественного выбора С помощью SQL Server

StackOverflow https://stackoverflow.com/questions/414138

  •  03-07-2019
  •  | 
  •  

Вопрос

Мне нужно отфильтровать результирующие наборы с sql server на основе выборок из списка с несколькими вариантами выбора.Я рассматривал идею выполнения instring, чтобы определить, существует ли значение строки в выбранных значениях фильтра, но это может привести к частичным совпадениям (напримерАвтомобиль соответствует Ковру).

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

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

Это было полезно?

Решение

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

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

Другая возможность - использовать 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

Другие советы

  

Я прошел через идею сделать   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)

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top