2015-08-08 3 views
4

У меня есть Books стол:Поиск путем разделения строки в нескольких столбцах таблицы SQL?

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

У вас нет плана для ввода трех разных текстовых полей? – Steve

+0

есть ли какой-нибудь заказ на поисковые слова? – DarkKnight

+0

Что делать, если пользователь вводит «9 E», если он найдет как английский, так и CBSE или ни один из них? –

ответ

0

Если вы можете разбить строку в C#, прежде чем отправить запрос и создать переменные, удерживающие детали например:

string1 = «9» строка2 = «Английский»

Затем вам нужно appened а '%' на каждой стороне дает вам:

string1 = "% 9%" строка2 =% английский%»

Затем передать запрос как:

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, где вам нужно будет создать множество экземпляров и подстрок.

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 
0

Для того, чтобы решить эту проблему, мы должны планировать, как прикрепить эту проблему в руке.

  1. Мы должны извлечь из входного поиска Название или Совет ценности и Количество значение, если оно доступно.
  2. Мы должны построить наш SQL Query в таком порядке, чтобы он соответствовал нашему значению извлечения из столбцов Title или Board.
  3. Мы должны попытаться найти Number матч в нашей SQL Query только если Number действительно извлекается (если он извлекается, чем он имеет значение, отличное от null или Whitespace).

SearchInput: Объект, представляющий входные значения поиска

public class SearchInput 
{ 
    public string TitleOrBoard { get; set; } 
    public string Number { get; set; } 
} 

CreateSearchInput: преобразование входной строки в указанную выше сущность.

Поиск, если первое значение в строке является числом. Если первое значение является числом, чем назначить его Number и удалите номер из входной строки.

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; 
} 

ConstructSearchQuery: Строительство 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); 
} 

Выход:

Search: Number[9] TitleOrBoard[English] 
SQL Query: SELECT * FROM Books WHERE ([Title] LIKE '%English%' OR [Board] LIKE '%English%') OR Class = '%9%' 

.NET Fiddle

+0

На самом деле сэр он вернет английские книги из всех классов, включая 9 класс, потому что или оператор. Можем ли мы получить более точный результат, т. Е. Только английские книги класса 9? Спасибо –

+0

@ RajnishSingh, просто измените 'OR Class..' на' AND Class..' –

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 '%' [email protected] +'%' 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 '%' [email protected] +'%' 
+0

Сэр, на самом деле вот две проблемы: –

+0

оба случая должны работать, пожалуйста, измените @ chk = '9 CBSE' и попробуйте – nazark

+0

Но сэр, если значение «CBSE 9»? –

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); 

строка запроса возвратит следующий запрос для этого Search Text:

Query

И за содержание таблицы вы дали в описании вопроса, результат этого запроса даст следующий результат:

Table result

Обе записи матча на 9 в Class колонки и CBSE в Board колонки. Вы можете сменить ANDs и ORs внутри построителя запросов, если вы хотите по-разному, но, как правило, это то, о чем вы просили. Надеюсь, поможет.

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". Каждый термин должен быть окружен двойными кавычками и разделен «И». (Вы также можете использовать символы OR, NOT, NEAR и wildcards, но я не уверен, что они вам нужны в вашем случае.)

Вот простой способ преобразования в булевский синтаксис, который вам нужен с использованием .NET regex (в основном, заменить каждая серия 1+ пространств с " AND " и окружать результат с большим количеством двойных кавычек):

// 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 лучших матчей с лучшими отсортированные первым.

Смежные вопросы