表格中有一些字段可以包含逗号分隔的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
答案 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