Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
 Проблема с дубликатами строк  [new]
Veligord
Member

Откуда: Москва
Сообщений: 92
Мне нужно написать запрос для поиска в базе данных статей по заголовку и тексту статьи. На вход идет то, что нужно найти. Строка поиска может состоять из нескольких слов разделенных пробелами. Нужно найти все статьи, где в заголовке или в тексте статьи содержится хотя бы одно слово из строки поиска.

Запрос я написал, но возникла проблема с дубликатами строк. Подскажите пожалуйста, как исправить запрос, чтобы не возникало дубликатов строк.

текст запроса:

ALTER PROCEDURE dbo.ffs_Articles_SearchInArticles
(
   @Search	nvarchar(256)
)
AS
SET NOCOUNT ON

DECLARE @pos      int,
        @textpos  int,
        @tmpstr   nvarchar(256),
        @tmpval   nvarchar(256),
        @delimiter nchar(1)
        
DECLARE @tbl TABLE (ID int)
                             
SET @delimiter = ' '
SET @textpos = 1
SET @pos = 1
SET @tmpval = ltrim(@Search)
SET @tmpval = rtrim(@tmpval)
SET @Search = ltrim(@Search)
SET @Search = rtrim(@Search)

WHILE @pos <> 0
BEGIN
	SET @pos = charindex(@delimiter, @tmpval)
	IF(@pos > 0)		
		SET @tmpstr = substring(@tmpval, @textpos, @pos - 1)
	ELSE
		SET @tmpstr = substring(@tmpval, @textpos, len(@tmpval))

	INSERT INTO @tbl(ID)
	SELECT ffs_Articles.ArticleID FROM ffs_Articles
		WHERE CHARINDEX(@tmpstr, Title) > 0 OR CHARINDEX(@tmpstr, Abstract) > 0
	SET @tmpval = substring(@tmpval, @pos + 1, len(@tmpval))
END
   
SELECT a.*, sc.Title AS SubCategoryTitle FROM ffs_Articles AS a
INNER JOIN ffs_SubCategories AS sc ON a.SubCategoryID = sc.CategoryID
INNER JOIN @tbl AS tb ON a.ArticleID = tb.ID
ORDER BY CASE when CHARINDEX(@Search, a.Title) > 0 OR CHARINDEX(@Search, Abstract) > 0 then 1 else 2 end
17 май 11, 12:07    [10663703]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с дубликатами строк  [new]
Glory
Member

Откуда:
Сообщений: 104751
Вместо INNER JOIN @tbl использовать EXISTS
17 май 11, 12:12    [10663731]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с дубликатами строк  [new]
kDnZP
Member [заблокирован]

Откуда: ★[msg=16399436]★[msg=20850760]
Сообщений: 11289
Veligord, ну так вы же инсертите каждый раз, когда находите вхождение? Простейший способ - DISTINCT по найденому, хотя ИМХО переписать все так, чтобы передавать табличную переменную со словами для поиска, если версия сервера позволяет, либо передовать строку, а внутрях разбирать на табличку - а дальше поиск по ней.
17 май 11, 12:13    [10663742]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с дубликатами строк  [new]
Veligord
Member

Откуда: Москва
Сообщений: 92
Glory, сделал с EXIXTS и дубликаты исчезли. Спасибо. Но все таки хотелось бы не удалять дубликаты из таблицы, а сделать так, чтобы их изначально не было.

SELECT a.*, sc.Title AS SubCategoryTitle FROM ffs_Articles AS a
INNER JOIN ffs_SubCategories AS sc ON a.SubCategoryID = sc.CategoryID
WHERE EXISTS (SELECT *  FROM @tbl AS tb WHERE a.ArticleID = tb.ID)
ORDER BY CASE when CHARINDEX(@Search, a.Title) > 0 OR CHARINDEX(@Search, Abstract) > 0 then 1 else 2 end

kDnZP, я могу написать запрос, чтобы получить табличку со словами для поиска. Но, что потом с ней делать?
17 май 11, 13:01    [10664085]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с дубликатами строк  [new]
Glory
Member

Откуда:
Сообщений: 104751
Veligord
Glory, сделал с EXIXTS и дубликаты исчезли. Спасибо. Но все таки хотелось бы не удалять дубликаты из таблицы, а сделать так, чтобы их изначально не было.

- а где вы "удаляете дубликаты из таблицы" ?
- и почему вы решили, что у вас "изначально" есть дубликаты ?
17 май 11, 13:04    [10664113]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с дубликатами строк  [new]
iap
Member

Откуда: Москва
Сообщений: 47142
SELECT a.*, sc.Title AS SubCategoryTitle FROM ffs_Articles AS a
INNER JOIN ffs_SubCategories AS sc ON a.SubCategoryID = sc.CategoryID
WHERE a.Abstact+N'%'+a.Title LIKE N'%'+REPLACE(REPLACE(REPLACE(REPLACE(@Search,N'[',N'[[]'),N'%',N'[%]'),N'_','[_]'),N' ',N'%')+N'%';
???
НЕ ПРОВЕРЯЛ!
17 май 11, 13:12    [10664190]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с дубликатами строк  [new]
Veligord
Member

Откуда: Москва
Сообщений: 92
К сожалению это проистекает из того, как я составил запрос. Строка поиска разделяется на отдельные слова и по каждому из этих слов слов производится выборка. После выборки каждый раз INSERT. Вот из-за этого в таблице @tbl появляются дубликаты. Я это проверял.
А на счет удаления дубликатов строк, признаю некорректно выразился, он не удаляются просто происходит проверка и берутся только уникальные строки.
17 май 11, 13:12    [10664195]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с дубликатами строк  [new]
iap
Member

Откуда: Москва
Сообщений: 47142
iap
SELECT a.*, sc.Title AS SubCategoryTitle FROM ffs_Articles AS a
INNER JOIN ffs_SubCategories AS sc ON a.SubCategoryID = sc.CategoryID
WHERE a.Abstact+N'%'+a.Title LIKE N'%'+REPLACE(REPLACE(REPLACE(REPLACE(@Search,N'[',N'[[]'),N'%',N'[%]'),N'_','[_]'),N' ',N'%')+N'%';
???
НЕ ПРОВЕРЯЛ!
Зачем я процент между Abstract и Title добавил?
SELECT a.*, sc.Title AS SubCategoryTitle FROM ffs_Articles AS a
INNER JOIN ffs_SubCategories AS sc ON a.SubCategoryID = sc.CategoryID
WHERE a.Abstact+N' '+a.Title LIKE N'%'+REPLACE(REPLACE(REPLACE(REPLACE(@Search,N'[',N'[[]'),N'%',N'[%]'),N'_','[_]'),N' ',N'%')+N'%';
17 май 11, 13:14    [10664211]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с дубликатами строк  [new]
Glory
Member

Откуда:
Сообщений: 104751
Veligord
К сожалению это проистекает из того, как я составил запрос. Строка поиска разделяется на отдельные слова и по каждому из этих слов слов производится выборка. После выборки каждый раз INSERT. Вот из-за этого в таблице @tbl появляются дубликаты. Я это проверял.

Ну так и зачем вы делаете "по каждому из этих слов слов производится выборка" ?
Нельзя сначала распарсить строку, а потом сделать поиск ?
17 май 11, 13:15    [10664220]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с дубликатами строк  [new]
SomewhereSomehow
Member

Откуда: Moscow
Сообщений: 2480
Блог
iap,

имхо ваш вариант не вполне подойдет автору, он же ищет любое вхождение хотя бы одного слова
declare @t table(a nvarchar(100))
insert into @t select 'hello dolly'
insert into @t select 'dolly hello'

declare @Search nvarchar(100)
set @Search = 'hello dolly'

select 
*
from
@t
where
a like N'%'+REPLACE(REPLACE(REPLACE(REPLACE(@Search,N'[',N'[[]'),N'%',N'[%]'),N'_','[_]'),N' ',N'%')+N'%'
17 май 11, 13:21    [10664267]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с дубликатами строк  [new]
Veligord
Member

Откуда: Москва
Сообщений: 92
iap, запрос работает, спасибо. Но он находит только те статьи, в которых строка для поиска присутствует целиком. А мне нужно, что находились также статьи, где присутствует хотя бы одно слово из строки поиска.
17 май 11, 13:22    [10664273]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с дубликатами строк  [new]
Veligord
Member

Откуда: Москва
Сообщений: 92
Извини, SomewhereSomehow, но я не очень понимаю чем ваш пример отличается от того примера, что привел iap.
17 май 11, 13:32    [10664341]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с дубликатами строк  [new]
Veligord
Member

Откуда: Москва
Сообщений: 92
Glory, что ты подразумеваешь по распарсить строку? Разделить ее на отдельные слова и засунуть в таблицу?
17 май 11, 13:33    [10664355]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с дубликатами строк  [new]
SomewhereSomehow
Member

Откуда: Moscow
Сообщений: 2480
Блог
Veligord,
Это и есть пример iap, я просто проиллюстрировал то о чем говорил, про вхождение.

По поводу примера, сделайте как посоветовал Glory, распарсите вашу строку на части в переменную таблицу, и в экзисте проверяйте на вхождение при помощи like. Все лучше чем в цикле несколько запросов делать и ид-шки доставать. Ну а если заморочиться посмотрите вот вариант решения. Что делать, когда Full-Text бессилен или зарисовки на тему LIKE '%искомое%'
17 май 11, 13:42    [10664418]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с дубликатами строк  [new]
Backs
Member

Откуда:
Сообщений: 45
Veligord,

А может использовать Fulltext index search? freetexttable или containstable? быстрее будет, да и возможностей больше
17 май 11, 13:43    [10664431]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с дубликатами строк  [new]
Veligord
Member

Откуда: Москва
Сообщений: 92
Backs, не знаю с Full-Text search ни когда не работал.
17 май 11, 13:56    [10664534]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с дубликатами строк  [new]
iap
Member

Откуда: Москва
Сообщений: 47142
SomewhereSomehow
iap,

имхо ваш вариант не вполне подойдет автору, он же ищет любое вхождение хотя бы одного слова
Действительно. Признаю свою ошибку!
Говорю же: НЕ ПРОВЕРЯЛ!

Ну, распарсить-то @Search на строки - пара пустяков: Массивы и Списки в SQL Server
Да и сколько раз мы тут на форуме строки парсили таблицей чисел! (Надо поискать)
Всё ж лучше, чем цикл по строкам
17 май 11, 14:00    [10664562]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с дубликатами строк  [new]
kDnZP
Member [заблокирован]

Откуда: ★[msg=16399436]★[msg=20850760]
Сообщений: 11289
Veligord,

create TABLE #t (a nvarchar(100))
insert into #t select 'hello dolly'
insert into #t select 'dolly hello'
insert into #t select 'test & test2'
insert into #t select 'test2 & test3'

create TABLE #Search (a nvarchar(100))
insert into #Search select 'hello'
insert into #Search select 'dolly'
insert into #Search select 'test'

DECLARE @ssql NVARCHAR(max)
SET @ssql='SELECT * FROM #t WHERE '
SELECT @ssql=@ssql+'CHARINDEX('''+a+''',a,1 )>0 OR ' FROM #Search
SELECT @ssql=@ssql+'1=0'
PRINT @ssql
EXEC(@ssql)

DROP TABLE #t
DROP TABLE #Search

Вот еще вариант, с ограничениями ессно))), но можно допилить. Только как пример.
17 май 11, 14:06    [10664605]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с дубликатами строк  [new]
Veligord
Member

Откуда: Москва
Сообщений: 92
Всем спасибо, использовал такой вариант:

DECLARE @pos      int,
        @textpos  int,
        @tmpstr   nvarchar(256),
        @tmpval   nvarchar(256),
        @delimiter nchar(1)
        
DECLARE @tbl1 TABLE (ID int)
                             
SET @delimiter = ' '
SET @textpos = 1
SET @pos = 1
SET @tmpval = ltrim(@Search)
SET @tmpval = rtrim(@tmpval)

WHILE @pos <> 0
BEGIN
	SET @pos = charindex(@delimiter, @tmpval)
	IF(@pos > 0)		
		SET @tmpstr = substring(@tmpval, @textpos, @pos - 1)
	ELSE
		SET @tmpstr = substring(@tmpval, @textpos, len(@tmpval))

	INSERT INTO @tbl1(word)
		VALUES (@tmpstr)
	SET @tmpval = substring(@tmpval, @pos + 1, len(@tmpval))
END

SELECT a.*, sc.Title AS SubCategoryTitle FROM ffs_Articles AS a
INNER JOIN ffs_SubCategories AS sc ON a.SubCategoryID = sc.CategoryID
WHERE EXISTS (SELECT * FROM @tbl1 AS tb WHERE a.Abstract + N' ' + a.Title LIKE N'%'+REPLACE(REPLACE(REPLACE(REPLACE(tb.word,N'[',N'[[]'),N'%',N'[%]'),N'_','[_]'),N' ',N'%')+N'%')
17 май 11, 14:18    [10664694]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с дубликатами строк  [new]
iap
Member

Откуда: Москва
Сообщений: 47142
Veligord
Всем спасибо, использовал такой вариант:[/src]
И всё-таки, он неправильный. Ибо ищет определённую последовательность заданных слов.
А надо-то заданные слова В ЛЮБОЙ ПОСЛЕДОВАТЕЛЬНОСТИ искать!

Я ж уже покаялся!
17 май 11, 14:25    [10664739]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с дубликатами строк  [new]
Veligord
Member

Откуда: Москва
Сообщений: 92
А никто не подскажет, как теперь отсортировать строки, так, чтобы первой строкой шла та где строка поиска присутствует полностью (или большая ее часть), а затем строки в которых вхождений слов из строки поиска все меньше и меньше, вплоть до той куда входит только одно слово из строки поиска (это будет последняя строка).

я попробовал сделать сортировку так, и в этом случае первой строкой действительно становится та строка, где строка поиска присутствует целиком, но остальные строки остаются не отсортированными.

SELECT a.*, sc.Title AS SubCategoryTitle FROM ffs_Articles AS a
INNER JOIN ffs_SubCategories AS sc ON a.SubCategoryID = sc.CategoryID
WHERE EXISTS (SELECT * FROM @tbl AS tb WHERE a.Abstract + N' ' + a.Title LIKE N'%'+REPLACE(REPLACE(REPLACE(REPLACE(tb.word,N'[',N'[[]'),N'%',N'[%]'),N'_','[_]'),N' ',N'%')+N'%')
ORDER BY CASE when CHARINDEX(@Search, a.Title) > 0 OR CHARINDEX(@Search, Abstract) > 0 then 1 else 2 end
17 май 11, 14:29    [10664769]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с дубликатами строк  [new]
SomewhereSomehow
Member

Откуда: Moscow
Сообщений: 2480
Блог
iap,

так вроде нормально все теперь (ну кроме того что реплейсы видимо надо было перенести в раздел парсинга или убрать совсем)?
17 май 11, 14:32    [10664790]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с дубликатами строк  [new]
Veligord
Member

Откуда: Москва
Сообщений: 92
iap, ну после того как я перевел строку поиска в таблицу, как раз в любой последовательности и ищется.
17 май 11, 14:34    [10664818]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с дубликатами строк  [new]
iap
Member

Откуда: Москва
Сообщений: 47142
SomewhereSomehow
iap,

так вроде нормально все теперь (ну кроме того что реплейсы видимо надо было перенести в раздел парсинга или убрать совсем)?
Чего-то я сегодня рассеяный
Табличную переменную-то и не заметил!

А REPLACEы позволяют присутствовать символам процента, подчёркивания и левой квадратной скобки в искомых словах.
Так что не стоит их убирать (разве что замену пробелов на проценты)
17 май 11, 14:38    [10664855]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с дубликатами строк  [new]
Veligord
Member

Откуда: Москва
Сообщений: 92
А как быть если слова разделены не одним пробелом, а несколькими? При том, что в разных местах их может быть разное количество.
17 май 11, 14:42    [10664888]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
Все форумы / Microsoft SQL Server Ответить