PostgreSQL中的短语比较

PostgreSQL中的短语比较,postgresql,Postgresql,如何在Postgres表中的varchar列中查找包含相同3个单词短语的行 其他问题中的大部分全文搜索建议都是将向量与特定查询进行比较,但我要查找的是与其他行一样包含任何3个单词短语的行 例如: SELECT * FROM types t1 WHERE EXISTS (SELECT * FROM types t2 WHERE t1.name phrase_matches t2.name AND t1

如何在Postgres表中的varchar列中查找包含相同3个单词短语的行

其他问题中的大部分全文搜索建议都是将向量与特定查询进行比较,但我要查找的是与其他行一样包含任何3个单词短语的行

例如:

SELECT * 
FROM types t1 
WHERE EXISTS (SELECT * 
              FROM types t2 
              WHERE t1.name phrase_matches t2.name 
                AND t1.id > t2.id)
这里,
phrase\u matches
是一个虚构的操作,其中

'my foo bar baz'短语与'foo bar baz whatever'匹配
返回
true

'my foo-bar-baz'短语与'foo-baz which bar'匹配
返回
false


编辑:为来自谷歌的任何人更新-没有临时表的解决方案,使用连接,在一个有18k行的表上花费了一个多小时。临时表版本总共在几秒钟内运行。

创建一个包含行ID的三角形表,然后在三角形列上进行自联接。浪费大量的空间,但这是最简单的方法。在以下方面的帮助下:


为行ID创建一个三角形表,然后在三角形列上进行自联接。浪费大量的空间,但这是最简单的方法。在以下方面的帮助下:


可能有更好的选择,但你也可以这样做。这不完全是你所要求的,但我相信你能用这个想法来推动它

select n.name from(
select x.name as xname,count(*) from 
(
  (
    select name,unnest(string_to_array(name2,' '))  as name2
                              from new
  )as x
    inner join
    (
        select name,unnest(string_to_array(name,' ')) as name1
         from new
    )as y
    on x.name2=y.name1 and y.id>x.id
) group by x.name having count(*)>=3)r inner join new n on r.xname=n.name
这里有一把同样的小提琴:


注意我的小提琴中没有id,但你可以自己做。

可能有更好的选择,但你也可以这样做。这不完全是你所要求的,但我相信你能用这个想法来推动它

select n.name from(
select x.name as xname,count(*) from 
(
  (
    select name,unnest(string_to_array(name2,' '))  as name2
                              from new
  )as x
    inner join
    (
        select name,unnest(string_to_array(name,' ')) as name1
         from new
    )as y
    on x.name2=y.name1 and y.id>x.id
) group by x.name having count(*)>=3)r inner join new n on r.xname=n.name
这里有一把同样的小提琴:

注意我的小提琴中没有id,但你可以自己做。

结果:

phrase
my foo bar baz
foo baz whatever bar
foo bar baz whatever
blah my foo bar blah
blah my foo baz blah
a                      b                      check_phrase
blah my foo bar blah   my foo bar baz         my foo bar
foo bar baz whatever   my foo bar baz         foo bar baz
my foo bar baz         foo bar baz whatever   foo bar baz
blah my foo baz blah   blah my foo bar blah   blah my foo
my foo bar baz         blah my foo bar blah   my foo bar
blah my foo bar blah   blah my foo baz blah   blah my foo
  • CTE
    words
    创建所有短语的所有单词列表。所有单词都会得到一个索引,以确保它们在短语中的原始顺序

  • CTE
    phrase\u parts
    创建所有可能的3个单词短语:对于每个原始短语,所有单词都连接在一起

  • 加入后,结果如下所示:

    phrase                 unnest   row_number   phrase                 unnest     row_number
    my foo bar baz         my       1            my foo bar baz         my         1
    my foo bar baz         my       1            my foo bar baz         foo        2
    my foo bar baz         my       1            my foo bar baz         bar        3
    my foo bar baz         my       1            my foo bar baz         baz        4
    my foo bar baz         foo      2            my foo bar baz         foo        2
    my foo bar baz         foo      2            my foo bar baz         bar        3
    my foo bar baz         foo      2            my foo bar baz         baz        4
    my foo bar baz         bar      3            my foo bar baz         bar        3
    my foo bar baz         bar      3            my foo bar baz         baz        4
    my foo bar baz         baz      4            my foo bar baz         baz        4
    foo baz whatever bar   foo      5            foo baz whatever bar   foo        5
    foo baz whatever bar   foo      5            foo baz whatever bar   baz        6
    foo baz whatever bar   foo      5            foo baz whatever bar   whatever   7
    foo baz whatever bar   foo      5            foo baz whatever bar   bar        8
    foo baz whatever bar   baz      6            foo baz whatever bar   baz        6
    ...
    
    使用,我可以通过以下方式聚合第二个
    unnest
    列:

    array_agg
    {my}
    {my,foo}
    {my,foo,bar}
    {my,foo,bar,baz}
    {foo}
    {foo,bar}
    {foo,bar,baz}
    {bar}
    {bar,baz}
    {baz}
    {foo}
    {foo,baz}
    {foo,baz,whatever}
    {foo,baz,whatever,bar}
    ...
    
    这将被过滤为
    数组长度=3
    ,并重新转换为字符串。结果是3个单词短语:

  • 最后一步是检查表中的所有短语是否包含3个单词短语中的任何一个(并且这些短语不等于它们的源短语)
  • 结果:

    phrase
    my foo bar baz
    foo baz whatever bar
    foo bar baz whatever
    blah my foo bar blah
    blah my foo baz blah
    
    a                      b                      check_phrase
    blah my foo bar blah   my foo bar baz         my foo bar
    foo bar baz whatever   my foo bar baz         foo bar baz
    my foo bar baz         foo bar baz whatever   foo bar baz
    blah my foo baz blah   blah my foo bar blah   blah my foo
    my foo bar baz         blah my foo bar blah   my foo bar
    blah my foo bar blah   blah my foo baz blah   blah my foo
    
  • CTE
    words
    创建所有短语的所有单词列表。所有单词都会得到一个索引,以确保它们在短语中的原始顺序

  • CTE
    phrase\u parts
    创建所有可能的3个单词短语:对于每个原始短语,所有单词都连接在一起

  • 加入后,结果如下所示:

    phrase                 unnest   row_number   phrase                 unnest     row_number
    my foo bar baz         my       1            my foo bar baz         my         1
    my foo bar baz         my       1            my foo bar baz         foo        2
    my foo bar baz         my       1            my foo bar baz         bar        3
    my foo bar baz         my       1            my foo bar baz         baz        4
    my foo bar baz         foo      2            my foo bar baz         foo        2
    my foo bar baz         foo      2            my foo bar baz         bar        3
    my foo bar baz         foo      2            my foo bar baz         baz        4
    my foo bar baz         bar      3            my foo bar baz         bar        3
    my foo bar baz         bar      3            my foo bar baz         baz        4
    my foo bar baz         baz      4            my foo bar baz         baz        4
    foo baz whatever bar   foo      5            foo baz whatever bar   foo        5
    foo baz whatever bar   foo      5            foo baz whatever bar   baz        6
    foo baz whatever bar   foo      5            foo baz whatever bar   whatever   7
    foo baz whatever bar   foo      5            foo baz whatever bar   bar        8
    foo baz whatever bar   baz      6            foo baz whatever bar   baz        6
    ...
    
    使用,我可以通过以下方式聚合第二个
    unnest
    列:

    array_agg
    {my}
    {my,foo}
    {my,foo,bar}
    {my,foo,bar,baz}
    {foo}
    {foo,bar}
    {foo,bar,baz}
    {bar}
    {bar,baz}
    {baz}
    {foo}
    {foo,baz}
    {foo,baz,whatever}
    {foo,baz,whatever,bar}
    ...
    
    这将被过滤为
    数组长度=3
    ,并重新转换为字符串。结果是3个单词短语:

  • 最后一步是检查表中的所有短语是否包含3个单词短语中的任何一个(并且这些短语不等于它们的源短语)

  • 但是我有一个无限(理论上)的短语集。这个答案并不预设任何特定数量的短语——它只会找到有共享短语的行——只要子短语长度设置好。我把你在问题中提到的三个放进去;这并不意味着你不能拥有更多。因此,我首先必须浏览表格,并用数据中可能出现的所有短语填充短语表格,对吗?我展示了两种方式-快速但占用大量空间,或者缓慢但不占用额外空间。你必须牺牲一个,你的选择。呃,不,我误解了,你也是<代码>短语是您的表格。在我的代码中,它只是为了说明你在OP中显示的起始数据。那里没有提取过程——这正是你所说的数据。如果它的列名与您的表不完全相同,或者表名不完全相同,请相应地进行调整。它甚至在评论中说“你的数据:),但我有一个无限(理论上)的短语集。这个答案并不预设任何特定数量的短语——它只找到有共享短语的行——只要设置了子短语长度。我把你在问题中提到的三个放进去;这并不意味着你不能拥有更多。因此,我首先必须浏览表格,并用数据中可能出现的所有短语填充短语表格,对吗?我展示了两种方式-快速但占用大量空间,或者缓慢但不占用额外空间。你必须牺牲一个,你的选择。呃,不,我误解了,你也是<代码>短语是您的表格。在我的代码中,它只是为了说明你在OP中显示的起始数据。那里没有提取过程——这正是你所说的数据。如果它的列名与您的表不完全相同,或者表名不完全相同,请相应地进行调整。它甚至在评论中说“你的数据:)