获取包含特定数字的字段的记录

时间:2016-08-11 07:48:07

标签: sql-server vb.net

表格中有一些字段可以包含逗号分隔的1,2或3位数字。如下例所示:

ID | digitField
1  |   4, 55
2  |   1 ,70,33
3  |   8 
4  |   9,22,43
5  |   1,833,3
6  |   77,9
7  |   33
8  |   2,3335
9  |   6, 33

现在有一些数字我想搜索并获取包含它的记录的ID。搜索这些记录的最佳方法是什么?

例如,我正在寻找每一次出现的数字33.在这种情况下,我想根据上面的例子得到这些记录:

2  |   1,70,33
7  |   33
9  |   6, 33

以下查询是否足够好并且没有冒险获得错误的结果,或者您能提供更好的解决方案吗?:

SELECT ID FROM table WHERE CONTAINS(digitField, '33');

此查询非常重要,因为结果ID将删除商店产品,因此我希望避免错误的结果。 请注意,在我们的案例中,包含3,833或3335的记录无法匹配,因为我们正在寻找33.请注意,可能是该字段之间的某些空格(已经实现但没有机会更改它)

寻找最佳解决方案。

在字符串中正确关闭查询的其他问题:

Using cnn As New SqlConnection(strcon)
cnn.Open()
'--Just in case remove all spaces from string in field Materials before
Using dad As New SqlDataAdapter(";WITH yourtable as ( SELECT ID, REPLACE(digitField, ' ', '') digitfield FROM tempDigit ) 
                        SELECT * FROM YourTable WHERE digitField = @matId
                        OR digitField LIKE @matId+',%'
                        OR digitField LIKE '%,'+@matId
                        OR digitField LIKE '%,'+@matId+',%'", cnn)
    dad.SelectCommand.Parameters.Add(New SqlParameter("@matId", matId.ToString))
    dad.Fill(dt)
    If dt IsNot Nothing AndAlso dt.Rows.Count > 0 Then
        result = dt
    End If
End Using
cnn.Close()
End Using

3 个答案:

答案 0 :(得分:1)

您需要一个值为 SPLIT 的表格,以便将digitField“展开”到记录中,所以

ID | digitField
1  |   4, 55
2  |   1 ,70,33
3  |   8 

将成为

ID | n  | digitField
1  | 1  | 4
1  | 2  | 55
2  | 1  | 1
2  | 2  | 70
2  | 3  | 33
3  | 1  | 8 

然后您将在此结果中搜索您的号码。

周围有许多分割功能,你可以谷歌为他们 我自己开发了我的:

CREATE FUNCTION [dbo].[FN_SPLIT]
/*
  MTW - FN_SPLIT()
  mtw@inbox.lv
*/
(
    @Line varchar(8000),
    @SplitOn varchar(10) = ','
)
RETURNS @RtnValue table
(
    Id INT NOT NULL IDENTITY(1,1) PRIMARY KEY CLUSTERED, -- VERY USEFUL TO MAKE JOINS AND TO CREATE THE UNIQUE INDEX ON SPLITTED STRINGS
    Data varchar(800) NOT NULL,
    UNIQUE (DATA, ID) -- THIS WILL MAKE REALLY FASTER THE QUERIES USING THIS FUNCTION
)
AS
BEGIN
    IF @Line IS NULL RETURN

    DECLARE @split_on_len INT = LEN(@SplitOn+'X')-1 -- TO CATCH TRAILING SPACES PROBLEM WITH LEN()
    DECLARE @line_len INT = LEN(@line+'X')-1
    DECLARE @start_at INT = 1
    DECLARE @end_at INT
    DECLARE @data_len INT

    WHILE 1=1
    BEGIN
        IF @start_at > @line_len BREAK;
        SET @end_at = CHARINDEX(@SplitOn, @Line, @start_at)
        SET @data_len = CASE @end_at WHEN 0 THEN @line_len ELSE @end_at-@start_at END
        INSERT INTO @RtnValue (data) VALUES( SUBSTRING(@Line,@start_at,@data_len));
        SET @start_at = @start_at + @data_len + @split_on_len
    END

    RETURN
END

所以你的查询将是:

;WITH
S AS (
    SELECT T.ID, X.Id N, RTRIM(LTRIM(X.Data)) digitField
    FROM T
    CROSS APPLY (
        SELECT *
        FROM FN_SPLIT(T.digitField, ',') F
    ) X
)
SELECT *
FROM S
WHERE digitField = '33'
ORDER BY 1,2

结果是:

ID  N   digitField
2   3   33
7   1   33
9   2   33

其中列N是您在原始digitField列中的数字位置

答案 1 :(得分:0)

使用CHARINDEX,您可以获得匹配结果:

SELECT *
FROM Table
WHERE CHARINDEX('33', digitField) >= 1;

使用给定的样本数据执行示例:

DECLARE @TestTable TABLE (ID INT, digitField VARCHAR (200));

INSERT INTO @TestTable (ID, digitField) VALUES
(1, '4, 55'),
(2, '1,70,33'),
(3, '8'), 
(4, '9,22,43'),
(5, '1,2,3'),
(6, '77,9'),
(7, '33'),
(8, '2,5'),
(9, '6, 33');

SELECT *
FROM @TestTable
WHERE CHARINDEX('33', digitField) >= 1;

输出:

ID  digitField
--------------
2   1,70,33
7   33
9   6, 33

答案 2 :(得分:0)

只需过滤出给定数字出现的所有可能变体。 如果字段可以包含空格 - 只需删除它们即可。

/questions/add

创建Sql参数

 
SELECT *
FROM YourTable
CROSS APPLY (SELECT REPLACE(digitField, ' ', '') AS pureField) digit
WHERE digit.pureField = @Exact        --if only one number in field
   OR digit.pureField LIKE @Begin   --if number in the beginning of text
   OR digit.pureField LIKE @End   --if number in the end of text
   OR digit.pureField LIKE @Middle --if number in the middle of text