AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 78407
Accepted
Dave Jarvis
Dave Jarvis
Asked: 2014-10-06 01:42:03 +0800 CST2014-10-06 01:42:03 +0800 CST 2014-10-06 01:42:03 +0800 CST

Sufixo correspondente mais longo ao usar funções agregadas

  • 772

Fundo

Procurando encontrar o sufixo de string correspondente mais longo.

Configurar

Considere o seguinte violino :

CREATE TABLE noun
    ("label" varchar(10))
;

INSERT INTO noun
    ("label")
VALUES
    ('bar'),
    ('blue bar'),
    ('red bar'),
    ('green bar'),
    ('purple bar'),
    ('handlebar')
;

CREATE TABLE noun_inflection
    ("label_singular" varchar(9), "label_plural" varchar(9))
;

INSERT INTO noun_inflection
    ("label_singular", "label_plural")
VALUES
    ('bar', 'bars'),
    ('handlebar', 'handlebar')
;

E a seguinte consulta:

select * from noun n, noun_inflection ni
where
  n.label = 'handlebar' and
  n.label ilike '%'||ni.label_singular;

Isso retorna duas linhas:

LABEL       | LABEL_SINGULAR | LABEL_PLURAL
------------+----------------+-------------
handlebar   | bar            | bars
handlebar   | handlebar      | handlebar

A primeira linha está correta, mas não desejada. Para este propósito específico, a distância de Levenshtein pode ser usada para eliminar a duplicata:

select * from noun n, noun_inflection ni
where
  n.label = 'handlebar' and
  n.label ilike '%'||ni.label_singular
order by
  levenshtein( n.label, ni.label_singular )
limit 1;

Isso reordena as linhas com base na semelhança do rótulo. Neste exemplo, "handlebar" corresponde exatamente a "handlebar" e tem uma distância de 0. Adicionar o limit 1restringe a consulta a uma única linha.

Problema

A configuração funciona, exceto que o PostgreSQL 9.1 não respeita os modificadores LIMIT em funções agregadas. Ou seja, o seguinte não funciona:

SELECT
  xmlagg( xmlement( ... ) ORDER BY levenshtein( ... ) LIMIT 1 )
FROM
  noun n, noun_inflection ni

O problema persiste. A palavra 'handlebar'corresponde a '%bar'e '%handlebar', portanto, isso retorna duas linhas, que, por sua vez, injetam dois elementos xml no documento XML resultante quando apenas um é esperado.

Atualização nº 1

Esclarecer:

select
  xmlagg(
    xmlelement(
      name "noun",
      trim( TRAILING label_singular FROM n.label ) || ni.label_plural
    )
  )
from
  noun n, noun_inflection ni
where
  n.label = 'handlebar' and
  n.label ilike '%'||ni.label_singular;

Isso deve retornar um único elemento XML 'handlebar'. Atualmente, ele retorna 'handlebars' e 'handlebar':

{ "Value": "<noun>handlebars</noun><noun>handlebar</noun>", "Type": "xml" }

A saída desejada é:

{ "Value": "<noun>handlebar</noun>", "Type": "xml" }

Atualização nº 2

Mesmo que o código a seguir resolva o problema do guidão/guidão, ele evita que vários substantivos diferentes sejam retornados:

select
  xmlagg(
    xmlelement(
      name "noun",
      trim( TRAILING label_singular FROM n.label ) || ni.label_plural
    )
  )
from
  noun n, noun_inflection ni
where
  n.label = 'handlebar' and
  n.label ilike '%'||ni.label_singular
group by n.label, ni.label_singular
order by levenshtein( n.label, ni.label_singular )
limit 1

Atualização nº 3

Isso parece exigir uma função armazenada. Algo na linha de:

  SELECT
    trim( TRAILING label_singular FROM p_noun ) || ni.label_plural
  FROM
    noun_inflection ni
  WHERE
    p_noun ILIKE '%'||ni.label_singular
  ORDER BY
    levenshtein( p_noun, ni.label_singular )
  LIMIT 1;

Pergunta

Como você combinaria e retornaria apenas a substring mais longa?

postgresql xml
  • 3 3 respostas
  • 321 Views

3 respostas

  • Voted
  1. Thomas Kejser
    2014-10-06T01:50:40+08:002014-10-06T01:50:40+08:00

    O que há de errado com (talvez óbvio demais?):

    select * from noun n, noun_inflection ni
    where
      n.label = 'handlebar' and
      n.label ilike '%'||ni.label_singular
    order by
      char_length(ni.label_singular) DESC
    limit 1;
    
    • 4
  2. Michael Green
    2014-10-08T01:27:44+08:002014-10-08T01:27:44+08:00

    Se você deseja a substring mais longa, isso significa que não há outra que seja mais longa. Um NOT EXISTSpredicado dará isso.

    select
        <whatever>
    from <your table> as aa
    where <predicates>
    and not exists
        (
        select 1
        from <your table> as bb
        where <predicates>
        and len(bb.SomeColumn) > len(aa.SomeColumn)
        );
    

    Claro que a len()função pode ser substituída por levenshtein()como mostram seus exemplos. A consulta correlacionada pode causar problemas de desempenho. Seu conjunto de valores de teste é suficientemente pequeno para pré-calcular os valores de função para cada um?

    Você pode usar uma das consultas rápidas, mas erradas, para reduzir os conjuntos iniciais a um superconjunto administrável das respostas corretas, que podem então ser processadas por um algoritmo lento, mas correto.

    • 1
  3. Best Answer
    Dave Jarvis
    2014-10-06T20:19:35+08:002014-10-06T20:19:35+08:00

    A única solução viável que encontrei foi escrever uma função:

      FUNCTION get_noun_inflection( p_noun text, ... params ... )
      -- ... body, declare, variable, etc. 
      SELECT
        CASE
          -- ... conditions ...
          THEN trim( TRAILING ni.label_singular FROM p_noun ) || ni.label_plural
          -- Noun in singular form (no pluralization)
          ELSE p_noun
        END
      FROM
        noun_inflection ni
      INTO
        v_result
      WHERE
        p_noun ILIKE '%'||ni.label_singular
      ORDER BY
        levenshtein( p_noun, ni.label_singular )
      LIMIT 1;
    
      IF NOT found THEN
        v_result := p_noun;
      END IF;
    
      RETURN v_result;
    
      -- ... exception handling, default values, cost, etc.
    

    Então use a função:

    select
      xmlagg(
        xmlelement(
          name "noun",
          get_noun_inflection( n.label )
        )
      )
    from
      noun n
    
    • 0

relate perguntas

  • Posso ativar o PITR depois que o banco de dados foi usado

  • Práticas recomendadas para executar a replicação atrasada do deslocamento de tempo

  • Os procedimentos armazenados impedem a injeção de SQL?

  • Sequências Biológicas do UniProt no PostgreSQL

  • Qual é a diferença entre a replicação do PostgreSQL 9.0 e o Slony-I?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve