我有一个Books
表:
Title Board Class
----------------------------------------
Interactive English CBSE 9
Interactive Math ICSE 10
Hindi CBSE 9
我在asp.net网站上有一个搜索文本框。如果用户输入
文本框中的"9 CBSE"
,我的选择查询应返回
Title Board Class
-----------------------------------------
Interactive English CBSE 9
Hindi CBSE 9
如果用户输入"9 English"
,则应返回
Title Board Class
------------------------------------------
Interactive English CBSE 9
那么我的选择查询应该将文本框值与所有这三列匹配?
答案 0 :(得分:1)
我无法验证这一点,因为我现在无法访问Sqlserver,但这应该可行:
select
*
from
books
where
patindex('%' + left(_textbox_contents_, charindex(' ') - 1) + '%', Title + Board + Class) > 0
and patindex('%' + substring(_textbox_contents_, charindex(' ') + 1) + '%', Title + Board + Class) > 0
答案 1 :(得分:0)
如果你可以在发送查询之前拆分c#中的字符串并创建包含部分的变量,例如:
string1 =“9” string2 =“英语”
然后你需要向每一方添加'%'给你:
string1 =“%9%” string2 =%英文%“
然后将查询传递为:
Select *
from books
where (title like string1
or title like string2)
or (board like string1
or board like string2)
or (class like string1
or class like string2);
我想在发送查询之前将搜索字符串拆分比尝试使用SQL更容易,在那里你需要做一堆instrings和substrings。
答案 2 :(得分:0)
为了解决这个问题,我们应该计划如何解决这个问题。
Title
或Board
列中的提取值匹配的顺序构建 SQL查询。Number
匹配,前提是Number
确实被提取出来(如果它被提取的话,它的值不同于{{1} }或null
)。SearchInput:表示搜索输入值的实体
Whitespace
CreateSearchInput:将输入字符串转换为上述实体。
搜索字符串中的第一个值是否为数字。如果第一个值是一个数字而不是将其分配给public class SearchInput
{
public string TitleOrBoard { get; set; }
public string Number { get; set; }
}
并从输入字符串中删除该数字。
Number
ConstructSearchQuery:根据public static SearchInput CreateSearchInput(string input)
{
var inputSplitted = input.Trim().Split(new [] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
int number;
string searchText = "";
if (int.TryParse(inputSplitted.First(), out number))
{
searchText = String.Join(" ", inputSplitted.Skip(1));
}
var searchInput = new SearchInput()
{
Number = number.ToString(),
TitleOrBoard = searchText
};
return searchInput;
}
实体值构建SQLQuery。
SearchInput
主要功能
public static string ConstructSearchQuery(SearchInput searchInput)
{
StringBuilder sb = new StringBuilder("SELECT * FROM Books WHERE");
sb.AppendFormat(" ([Title] LIKE '%{0}%' OR [Board] LIKE '%{0}%')", searchInput.TitleOrBoard);
if (!String.IsNullOrWhiteSpace(searchInput.Number))
{
sb.AppendFormat(" OR Class = '%{0}%'", searchInput.Number);
}
return sb.ToString();
}
<强>输出:强>
public static void Main()
{
string input = "9 English";
var searchInput = CreateSearchInput(input);
string sqlQuery = ConstructSearchQuery(searchInput);
Console.WriteLine("Search: Number[{0}] TitleOrBoard[{1}]", searchInput.Number, searchInput.TitleOrBoard);
Console.WriteLine("SQL Query: {0}", sqlQuery);
}
答案 3 :(得分:0)
try this,
declare @t table (Title varchar(100), Board varchar(10), Class int)
declare @chk varchar(10)='9 English'
insert into @t (Title, Board, Class) values
('Interactive English','CBSE',9),
('Interactive Math','ICSE',10),
('Hindi','CBSE',9)
select * from @t where cast(Class as varchar(2)) +' '+Board like '%' + @chk +'%'
or Board +' '+cast(Class as varchar(2)) like '%' + @chk +'%' or
cast(Class as varchar(2)) +' '+case when charindex(' ', title)=0 then
title else REverse(substring(reverse(title),1,charindex(' ', REVERSE(title))-1)) end
like '%' +@chk +'%' or
case when charindex(' ', title)=0 then
title else REverse(substring(reverse(title),1,charindex(' ', REVERSE(title))-1)) end +' '+cast(Class as varchar(2))
like '%' +@chk +'%'
答案 4 :(得分:0)
如果您愿意找到所有搜索关键字至少匹配一个值的结果,那么这应该对您有用:
private string BuildQueryString(List<string> keywords)
{
List<string> numbers = keywords.Where(keyword => keyword.All(Char.IsDigit))
.ToList();
List<string> words = keywords.Except(numbers)
.Select(keyword => string.Format("('{0}')", keyword))
.ToList();
var queryBuilder = new StringBuilder();
if (words.Count > 0)
{
queryBuilder.AppendFormat(@"
CREATE TABLE #Keywords
(
Keyword NVARCHAR(MAX)
)
INSERT INTO #Keywords (Keyword)
VALUES {0} ",
string.Join(", ", words));
}
queryBuilder.AppendFormat(@"
SELECT Title, Board, Class
FROM Books ");
string numbersFilter = string.Format("Class IN ({0})", string.Join(", ", numbers));
string wordsFilter = @"EXISTS (SELECT TOP 1 1
FROM #Keywords
WHERE Title LIKE '%' + Keyword + '%'
OR Board LIKE '%' + Keyword + '%')";
if (numbers.Count > 0 && words.Count > 0)
{
queryBuilder.AppendFormat(@"
WHERE {0} AND {1}", numbersFilter, wordsFilter);
}
else if (numbers.Count > 0)
{
queryBuilder.AppendFormat(@"
WHERE {0}", numbersFilter);
}
else if (words.Count > 0)
{
queryBuilder.AppendFormat(@"
WHERE {0}", wordsFilter);
}
return queryBuilder.ToString();
}
用例示例:
txtSearch.Text = "CBSE 9 MEH 23 Hey 90 N0 Word1";
List<string> keywords = txtSearch.Text
.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
.ToList();
string queryString = BuildQueryString(keywords);
您的查询字符串将返回此搜索文本的下一个查询:
对于您在问题描述中提供的表格内容,此查询的结果将产生下一个结果:
这两个记录都与Class
列中的9和Board
列中的CBSE相匹配。如果您想要不同的行为,可以在查询构建器中更改 ANDs 和 ORs ,但通常,这就是您要求的。希望它有所帮助。
答案 5 :(得分:0)
使用全文查询,您可以为最终用户提供构建搜索的灵活性。此外,您不需要对搜索字符串执行尽可能多的解析,并且搜索通常比使用LIKE更快。
<强> 1。创建全文目录和索引。
CREATE FULLTEXT CATALOG [ftcat_Books] WITH ACCENT_SENSITIVITY = OFF
GO
CREATE FULLTEXT INDEX ON [Books] ([Title] LANGUAGE 'English', [Board] LANGUAGE 'English', [Class] LANGUAGE 'English')
KEY INDEX [PK_Books] ON ([ftcat_Books], FILEGROUP [PRIMARY])
WITH (CHANGE_TRACKING = AUTO, STOPLIST = OFF)
您的Books.Class列必须为varchar或nvarchar才能生效。
我建议不要使用任何名单(STOPLIST = OFF
),这样就不会忽略单个数字,例如你的例子中的9。
More about accent sensitivity(此示例不使用重音敏感度)
More about change tracking(此示例使用更改跟踪)
<强> 2。将用户查询转换为布尔语法。
当用户输入9 CBSE
时,必须将其转换为"9" AND "CBSE"
。每个术语必须用双引号括起来并用&#34; AND&#34;分隔。 (您也可以使用OR,NOT,NEAR和通配符,但我不确定您是否需要它们。)
这里是一种使用.NET正则表达式转换为所需布尔语法的简单方法(基本上,用" AND "
替换每个1+空格的系列,并用更多双引号括起结果):
// assume searchString = "9 CBSE"
string searchStringBoolean = "\"" + Regex.Replace(searchString, @"\s+", "\" AND \"") + "\"";
请记住,这是一种非常简单的方法。如果用户已在其搜索字符串中键入双引号或AND,则需要考虑该怎么做。
第3。运行全文查询。
-- @SearchStringBoolean is the boolean string created in step 2
SELECT TOP 100 Books.Title, Books.Board, Books.Class
FROM ContainsTable(Books, *, @SearchStringBoolean) as FullTextResults
join Books on FullTextResults.KEY = Books.Id
ORDER BY FullTextResults.RANK desc
这将返回前100个匹配项,其中包含最先排序的最佳匹配项。