Фильтрация с помощью полей множественного выбора С помощью SQL Server
-
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.