【问题标题】:Search for in a delimited string column在分隔的字符串列中搜索
【发布时间】:2012-04-03 11:37:57
【问题描述】:

我有一个这样的搜索字符串:'value1,value4,value8'

我有一个像这样的条目的数据库表:

id   |    value
-----+------------------------
1    |    value1,value2,value3
2    |    value3,value4,value9
3    |    value4,value8,value9
4    |    value2,value3,value9

现在我正在寻找一种方法来搜索数据库中包含 value1、value4 或 value8 的所有记录。

在此示例中,我在进行选择时需要记录 1、2 和 3。

我已经有一个拆分函数,可以将我的搜索字符串拆分为 IN VALUES,如下所示:'value1'、'value4'、'value8',但我无法让它工作以选择正确的记录。

谢谢。

【问题讨论】:

  • 你知道数据不是第三范式吗?您是否考虑过先修复数据,然后 TSQL 语法更简单,查询执行效率更高?
  • 根据你想要的记录 1,2 和 3 那么你的意思是包含 value1, value4, OR value8
  • 你的意思是一个包含所有值的表和一个引用这些值的 id 的表?
  • 一行。记录 1 不包含 value1、value4、AND value8。记录 1 包含 value1、value4、OR value8。

标签: sql-server sql-server-2008 tsql split


【解决方案1】:

可能是这样的:

测试数据

CREATE TABLE Table1
(
    id INT,
    value VARCHAR(200)
)
INSERT INTO Table1
VALUES
    (1,'value1,value2,value3'),
    (2,'value3,value4,value9'),
    (3,'value4,value8,value9'),
    (4,'value2,value3,value9')

拆分功能

CREATE FUNCTION dbo.Split (@sep char(1), @s varchar(512))
RETURNS table
AS
RETURN (
    WITH Pieces(pn, start, stop) AS (
      SELECT 1, 1, CHARINDEX(@sep, @s)
      UNION ALL
      SELECT pn + 1, stop + 1, CHARINDEX(@sep, @s, stop + 1)
      FROM Pieces
      WHERE stop > 0
    )
    SELECT pn,
      SUBSTRING(@s, start, CASE WHEN stop > 0 THEN stop-start ELSE 512 END) AS s
    FROM Pieces
  )
GO

查询

DECLARE @searchString VARCHAR(100)
SET @searchString='value1,value4,value8'
;WITH CTE
AS
(
    SELECT 
        split.s as searchString
    FROM 
        dbo.Split(',',@searchString) AS split
)
SELECT
    *
FROM
    Table1
WHERE EXISTS
(
    SELECT
        NULL
    FROM
        dbo.Split(',',Table1.value) AS split
    WHERE EXISTS
    (
        SELECT
            NULL
        FROM
            CTE
        WHERE
            CTE.searchString=split.s
    )
)

结果

id      value
1       value1,value2,value3
2       value3,value4,value9
3       value4,value8,value9

编辑

这个分割函数接受一个分隔符和varchar 来分割。它是一个递归函数,用于计算输入varchar 中sperator 所在位置的开始和结束。当计算出开始和结束时,substring 很容易执行。

【讨论】:

  • 没问题。如果您对答案没问题,可能会考虑接受它。如果您认为答案很好,请记得投票。它给了我们所有温暖模糊的感觉
【解决方案2】:

为了得到你想要的,我认为你要么需要将你的分隔结果(不带单引号)插入到一个临时表中,要么让你的拆分函数返回一个表。然后你可以说:

SELECT column1, column2, column3 
FROM table1
WHERE value in (select * from #values)

WHERE value in (select * from dbo.StringSplitFunc(...))

取决于您采用哪种方法。

【讨论】:

    【解决方案3】:

    如果您在代码中有匹配的值并且它将是静态的,这可能会起作用:

    select * from table where value like '%value1%' and value like '%value4%' and value like '%value8%'
    

    这是如果您希望它包含所有值。如果您希望它包含 or 然后您将 'and' 切换为 'or'

    编辑:

    在代码中有值,您可以在代码中动态构建 SQL 语句。

    string statement = "select * from table where value like '%value%'";
    foreach (string value in collectionOfValues) {
          statement += " and value like '" + value + "'";
    }
    

    我当然会使用 SqlParameters 而不是直接将值放入语句中,但你明白我的意思。

    【讨论】:

    • 我从代码中得到的搜索字符串,是动态的。所以它可以是一个值或六个值或其他值。所以我必须拆分搜索字符串并从中做出选择语句。
    • 上次编辑我的帖子时,我明白你想要什么了吗?
    • 是的,我明白了。但我正在寻找一种在存储过程中完成这一切的解决方案。
    • 我会调查一下,但我可能会问您为什么更喜欢在存储过程中执行此操作?有什么优势?
    • 您可能希望使用WHERE ',' + value + ',' LIKE '%,valueX,%' 来避免误点击。例如。如果没有逗号,您可能会在查找 value4 时匹配 value48
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-19
    相关资源
    最近更新 更多