【问题标题】:Compare if two strings contain the same words比较两个字符串是否包含相同的单词
【发布时间】:2021-04-16 09:00:33
【问题描述】:

我有两个字符串:

'one two three'

'two one three'

虽然如果我直接比较它们,它们是不一样的,但它们分别包含的值是相同的,这对我来说很重要。所以我对比较的回答是字符串是相等的。 我正在寻找更直接的方法来比较它们,而无需创建函数来拆分和比较每个单独的值。有没有这样的解决方案?

我在stackoverflow中找到了这个线程:How to compare if two strings contain the same words in T-SQL for SQL Server 2008?

这对我不起作用,因为我想在进行其他比较的 cte 中进行此比较。

【问题讨论】:

  • 根据问题指南,请展示您的尝试并告诉我们您发现了什么(在本网站或其他地方)以及为什么它不能满足您的需求。
  • 您需要使用字符串拆分器拆分字符串,然后确保该值存在于另一个字符串中(也已拆分)。老实说,T-SQL 远非最好的语言选择。
  • I want to make this comparison on the go in a cte 在这种情况下,我建议创建一个封装拆分和比较的用户定义函数。或者创建一个拆分、排序和重新加入的转换函数,然后为每个字符串调用一次并比较两个转换的结果 -> 请参阅您自己发布的链接中的dbo.StringSorter。这将属于我对直截了当的定义,或者仍然是最不麻烦的方式。
  • 如果另一个字符串是two three fourone two three four你想要什么结果
  • @Charlieface 这将是错误的。

标签: sql sql-server string string-comparison


【解决方案1】:

必须拆分字符串,否则如何比较单独的部分。

我假设您要查找所有匹配的项目对。我已经通过一张表的自联接展示了这一点,但您同样可以从两张表中做到这一点。

这是Relational Division Without Remainder的问题,有很多解决方案。

DECLARE @t table (val varchar(100));

INSERT @t(col) values('one three two'), ('three   two one'), ('one two    three'), (' one two two    three three   ');


SELECT *
FROM @t t1
JOIN @t t2 ON EXISTS (
    SELECT 1
    FROM STRING_SPLIT(t1.val, ' ') s1
    LEFT JOIN STRING_SPLIT(t2.val, ' ') s2 ON s2.value = s1.value
    HAVING COUNT(CASE WHEN s2.value IS NULL THEN 1) = 0
      AND COUNT(*) = (SELECT COUNT(*) FROM STRING_SPLIT(t2.val, ' '))
);

SELECT *
FROM @t t1
JOIN @t t2 ON (
        SELECT STRING_AGG(s1.value, ' ') WITHIN GROUP (ORDER BY s1.value)
        FROM STRING_SPLIT(t1.val, ' ') s1
    ) = (
        SELECT STRING_AGG(s2.value, ' ') WITHIN GROUP (ORDER BY s2.value)
        FROM STRING_SPLIT(t2.val, ' ') s2
    )
);

【讨论】:

    【解决方案2】:

    使用 T-SQL 和 XQuery 比较容易实现。特别是通过使用 XQuery 的量化表达式

    这是它的工作原理:

    1. 将输入世界列表转换为 XML,即标记化过程。
    2. 运行量化表达式。单词的顺序无关紧要。
    3. 计算源和目标中的单词数。
    4. (#2 和#3)两者的结果都是最终结果。

    SQL

    -- DDL and sample data population, start
    DECLARE @tbl TABLE( ID INT IDENTITY PRIMARY KEY, WordList1 VARCHAR(1024), WordList2 VARCHAR(1024));
    INSERT INTO @tbl (WordList1, WordList2) VALUES
    ('one two three', 'two one three'),
    ('one two three', 'two   one   three  '),
    ('one two    three', ' one two two    three three');
    -- DDL and sample data population, end
    
    DECLARE @Separator CHAR(1) = SPACE(1);
    
    ;WITH rs AS
    (
        SELECT *
           , TRY_CAST('<root><source><r>' + REPLACE(WordList1, @Separator, '</r><r>') + '</r></source>'
              + '<target><r>' + REPLACE(WordList2, @Separator, '</r><r>') + '</r></target></root>' AS XML) AS xmldata
        FROM @tbl
    )
    SELECT * 
        , xmldata.value('every $x in /root/source/r[text()]/text()
                    satisfies ($x = (/root/target/r[text()]/text())
                  and (count(/root/source/r[text()]) eq count(/root/target/r[text()])))', 'BIT') AS result
    FROM rs;
    

    输出

    +----+-----------------+---------------------------+--------+
    | ID |    WordList1    |         WordList2         | result |
    +----+-----------------+---------------------------+--------+
    |  1 | one two three   | two one three             |      1 |
    |  2 | one two three   | two   one   three         |      1 |
    |  3 | one two   three |  one two two  three three |      0 |
    +----+-----------------+---------------------------+--------+
    

    【讨论】:

      【解决方案3】:

      --.... > SQL2017

      declare @t table(col varchar(400));
      insert into @t(col) values('one three two'), ('three   two one'), ('one two    three'), (' one two two    three three   ');
      
      select *, 
      (
      /*
      select string_agg(value, ' ') within group (order by value)
      from openjson(concat('["', replace(string_escape( col, 'json' ) , ' ', '","'), '"]'))
      where value <> ''
      */
      select string_agg(value, ' ') within group (order by value)
      from 
      (
      select distinct value
      from openjson(concat('["', replace(string_escape(col, 'json' ) , ' ', '","'), '"]'))
      where value <> ''
      ) as s
      ) as rearranged
      from @t;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-11-07
        • 2019-04-27
        • 2018-04-19
        • 2018-09-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多