Как сравнить, если две строки содержат одинаковые слова в T-SQL для SQL Server 2008? - PullRequest
7 голосов
/ 16 марта 2012

Когда я сравниваю две строки в SQL Server, есть несколько простых способов с = или LIKE.

Я хочу переопределить равенство как:

Если две строки содержат одинаковые слова - независимо от того, в каком порядке - они равны, в противном случае они не равны.

Например:

  • 'my word' и 'word my' равны
  • 'my word' и 'aaamy word' не

Какое простое решение для этой проблемы?

Ответы [ 8 ]

4 голосов
/ 16 марта 2012

Я не думаю, что есть простое решение для того, что вы пытаетесь сделать в SQL Server. Моей первой мыслью было бы создать CLR UDF, который:

  1. Принимает две строки
  2. Разбивает их на два массива, используя функцию разделения на ""
  3. Сравните содержимое двух массивов, вернув true, если они содержат одинаковые элементы.

Если вы хотите пойти по этому маршруту, посмотрите эту статью , чтобы начать создавать пользовательские функции CLR.

2 голосов
/ 04 мая 2012

Попробуйте это ... Функция StringSorter разбивает строки на пробел, а затем сортирует все слова и помещает строку обратно в отсортированный порядок слов.

CREATE FUNCTION dbo.StringSorter(@sep char(1), @s varchar(8000))
RETURNS varchar(8000)
AS
BEGIN
    DECLARE @ResultVar varchar(8000);

    WITH sorter_cte AS (
      SELECT CHARINDEX(@sep, @s) as pos, 0 as lastPos
      UNION ALL
      SELECT CHARINDEX(@sep, @s, pos + 1), pos
      FROM sorter_cte
      WHERE pos > 0
    )
    , step2_cte AS (
    SELECT SUBSTRING(@s, lastPos + 1,
             case when pos = 0 then 80000
             else pos - lastPos -1 end) as chunk
    FROM sorter_cte
    )
    SELECT @ResultVar = (select ' ' + chunk 
                                     from step2_cte 
                                     order by chunk 
                                     FOR XML PATH(''));
    RETURN @ResultVar;
END
GO

Вот тестовый пример, который просто пробуетфункция:

SELECT dbo.StringSorter(' ', 'the quick brown dog jumped over the lazy fox');

, которая дала следующие результаты:

  brown dog fox jumped lazy over quick the the

Затем, чтобы запустить его из оператора выбора, используя ваши строки

SELECT case when dbo.StringSorter(' ', 'my word') = 
                     dbo.StringSorter(' ', 'word my') 
               then 'Equal' else 'Not Equal' end as ResultCheck
SELECT case when dbo.StringSorter(' ', 'my word') = 
                     dbo.StringSorter(' ', 'aaamy word') 
               then 'Equal' else 'Not Equal' end as ResultCheck

Первый показываетчто они равны, а второе - нет.

Это должно делать именно то, что вы ищете, с помощью простой функции, использующей рекурсивный CTE для сортировки вашей строки.

Наслаждайтесь!

1 голос
/ 06 ноября 2012

ОЧЕНЬ простой способ сделать это ... JC65100

ALTER FUNCTION [dbo].[ITS_GetDifCharCount] 
(
@str1 VARCHAR(MAX)
,@str2 VARCHAR(MAX)
)
RETURNS INT
AS
BEGIN
DECLARE @result INT

SELECT @result = COUNT(*)
FROM dbo.ITS_CompareStrs(@str1,@str2 )

RETURN @result

END


ALTER FUNCTION [dbo].[ITS_CompareStrs]
(
@str1 VARCHAR(MAX)
,@str2 VARCHAR(MAX)
)
RETURNS 
@Result TABLE  (ind INT, c1 char(1), c2 char(1))
AS
BEGIN
    DECLARE @i AS INT
             ,@c1 CHAR(1)
             ,@c2 CHAR(1)

    SET @i = 1

    WHILE LEN (@str1) > @i-1  OR LEN (@str2) > @i-1   
    BEGIN

      IF LEN (@str1) > @i-1
        SET @c1 = substring(@str1, @i, 1)  

      IF LEN (@str2) > @i-1
        SET @c2 = substring(@str2, @i, 1)

      INSERT INTO @Result([ind],c1,c2)
      SELECT @i,@c1,@c2

      SELECT @i=@i+1
              ,@c1=NULL
              ,@c2=NULL

    END

    DELETE FROM @Result
    WHERE c1=c2


RETURN 
END
1 голос
/ 16 марта 2012

Сценарий выглядит следующим образом. Вы хотели бы использовать TVF, чтобы разделить первую и вторую строки на пробел, а затем full join получившиеся две таблицы значений, и если у вас нулевые значения слева или справа, вы получите неравенство, в противном случае они равны.

1 голос
/ 16 марта 2012

Нет простого способа сделать это.Рекомендуется написать функцию или хранимую процедуру, которые он обрабатывает, связанные с этим требованием.

Ваша функция может использовать другие функции, которые разбивают строки на части, сортируют по словам и т. Д.

Воткак можно разбить строки:

T-SQL: в отличие от конкатенации строк - как разбить строку на несколько записей

0 голосов
/ 04 мая 2012
declare @s1 varchar(50) = 'my word'
declare @s2 varchar(50) = 'word my'

declare @t1 table (word varchar(50))

while len(@s1)>0 
begin
    if (CHARINDEX(' ', @s1)>0)
    begin       
        insert into @t1 values(ltrim(rtrim(LEFT(@s1, charindex(' ', @s1)))))        
        set @s1 = LTRIM(rtrim(right(@s1, len(@s1)-charindex(' ', @s1))))
    end
    else
    begin
        insert into @t1 values (@s1)
        set @s1=''      
    end     
end

declare @t2 table (word varchar(50))
while len(@s2)>0 
begin
    if (CHARINDEX(' ', @s2)>0)
    begin       
        insert into @t2 values(ltrim(rtrim(LEFT(@s2, charindex(' ', @s2)))))        
        set @s2 = LTRIM(rtrim(right(@s2, len(@s2)-charindex(' ', @s2))))
    end
    else
    begin
        insert into @t2 values (@s2)
        set @s2=''      
    end     
end

select case when exists(SELECT * FROM @t1 EXCEPT SELECT * FROM @t2) then 'are not' else 'are equal' end
0 голосов
/ 18 апреля 2012

Существует библиотека с именем http://www.sqlsharp.com/, которая содержит целый ряд полезных строковых / математических функций.

Он имеет функцию String_CompareSplitValues, которая делает именно то, что вы хотите.

Я не уверен, что это версия для сообщества или платная версия.

0 голосов
/ 16 марта 2012

Вы можете добавить предварительно вычисленный столбец в базовую таблицу, который оценивается в триггере INSERT / UPDATE (или UDF по умолчанию), который разбивает, сортирует и затем объединяет слова из исходного столбца.

Затем используйте = для сравненияэти предварительно вычисленные столбцы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...