sql server—在sql中,如何检查与另一行相似的行值

zrfyljdw  于 2021-07-29  发布在  Java
关注(0)|答案(3)|浏览(423)

我正在使用sqlserver(t-sql)。我有一列的行值为a、ab、、ac。我想删除另一行中包含的任何值。在这种情况下,我只剩下和ac,因为a和ab包含在另外两个中。
我的想法是获取列的每个值,并使用like搜索整个列,然后计算返回的结果数如果它等于1,则不包含在其他行中。
这是个好办法吗?我问是因为我不愿意使用循环/光标。
谢谢
以下是从上述解释中提取的代码示例:

CREATE TABLE #t (words varchar(10))
INSERT INTO #t 
VALUES ('A'),('AB'),('ABC'),('AC')

使用光标,我想我会做一些类似的事情:

DECLARE @branches TABLE (words varchar(10), n int)
DECLARE @word VARCHAR(10)
DECLARE cursor_word CURSOR

FOR SELECT words FROM #t

OPEN cursor_word;
FETCH NEXT FROM cursor_word INTO @word
WHILE @@FETCH_STATUS = 0
    BEGIN
        INSERT INTO @branches SELECT @word, COUNT(*) FROM #t WHERE words like CONCAT('%', @word ,'%')
        FETCH NEXT FROM cursor_word INTO @word
    END

CLOSE cursor_word
DEALLOCATE cursor_word

SELECT * FROM @branches WHERE n = 1
wlp8pajw

wlp8pajw1#

我会用 not exists ,但不需要主键:

select t.*
from t
where not exists (select 1
                  from t t2
                  where t2.words like '%' + t.words + '%' and
                        t2.words <> t.words
                 );

这是一把小提琴。
您描述的方法是:

select t.*
from t
where (select count(*)
       from t t2
       where t2.words like '%' + t.words + '%' 
      ) = 1;

如果没有副本,这在功能上等同于 not exists 版本。然而, not exists 好多了。为什么?聚合版本必须遍历每一行来计算计数。这个 not exists 版本可以在第一次匹配时停止--这可以显著减少 like 比较。

jmp7cifd

jmp7cifd2#

你可以试试

SELECT *
FROM (
    SELECT *
    , Row_Number() OVER(ORDER BY Words) N -- Create identifier for the row
    FROM #t
) t1
LEFT JOIN (
    SELECT *
    , Row_Number() OVER(ORDER BY Words) N -- Create identifier for the row
    FROM #t 
) t2 on t1.N <> t2.n -- Where the identifier is different 
    AND t2.Words LIKE t1.Words + '%' -- Where t2.Words starts with t1.Words
WHERE t2.Words IS NULL -- And there is no match of t2.
gojuced7

gojuced73#

我只想利用 not exists 为了这个。这需要在表中有一个主键(无论如何这是必须的),所以让我假设 id :

select t.*
from mytable t
where not exists (
    select 1 
    from mytable t1 
    where t1.id <> t.id and t1.word like '%' + t.word + '%'
)

相关问题