2

我需要根据多选列表框中的选择过滤来自 sql server 的结果集。我已经考虑过使用 instring 来确定所选过滤器值中是否存在行值,但这很容易出现部分匹配(例如 Car 匹配 Carpet)。

我还经历了将字符串拆分成一个表并基于此加入/匹配,但我对它的执行方式持保留态度。

鉴于这是一项看似常见的任务,我正在向 Stack Overflow 社区寻求一些反馈,并可能就解决此问题的最常用方法提出一些建议。

4

3 回答 3

4

我通过编写一个表值函数(我们使用的是 2005)解决了这个问题,该函数接受一个分隔字符串并返回一个表。然后你可以加入到那个或使用 WHERE EXISTS 或 WHERE x IN。我们还没有进行全面的压力测试,但是由于使用有限和相当小的项目集,我认为性能应该还可以。

以下是作为您起点的功能之一。我还写了一个专门接受查找表中 ID 值的分隔 INT 列表等。

另一种可能性是将 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
于 2009-01-05T19:31:40.107 回答
1

我已经考虑过使用 instring 来确定所选过滤器值中是否存在行值,但这很容易出现部分匹配(例如 Car 匹配 Carpet)

在我看来,您没有包含唯一 ID,或者可能没有将主键作为列表框中值的一部分。理想情况下,每个选项都有一个唯一标识符,该标识符与您正在搜索的表中的列相匹配。如果您的列表框如下所示,那么您将能够专门针对汽车进行过滤,因为您将获得唯一值 3。

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

然后,您只需构建一个 where 子句,该子句将允许您找到所需的值。


更新,回答评论。

考虑到用户可以从列表框中选择任意数量的选项,我将如何进行相关连接?SELECT * FROM tblTable 加入 tblOptions ON tblTable.FK = ? 这里的问题是我需要加入多个值。

我在这里回答了一个类似的问题。

一种方法是构建一个临时表并将每个选定的选项作为一行添加到临时表中。然后,您只需连接到您的临时表。

如果你想简单地动态创建你的 sql,你可以做这样的事情。

SELECT * FROM tblTable WHERE option IN (selected_option_1, selected_option_2, selected_option_n)
于 2009-01-05T20:10:33.803 回答
0

我发现一个 CLR 表值函数接受你的分隔字符串并在字符串上调用 Split(将数组作为 IEnumerable 返回)比用 T-SQL 编写的任何东西都更高效(当你有它时它开始崩溃分隔列表中有 100 万个项目,但这比 T-SQL 解决方案要远得多)。

然后,您可以加入表或检查 EXISTS。

于 2009-01-05T21:32:02.517 回答