Estou trabalhando no PostgreSQL e tenho uma tabela como esta chamada words_table:
Eu preciso de todas as palavras equivalentes (como software_design e software-design) para ter seu valor de mapa = para id_word equivalente de sua palavra. Em outras palavras, quero que todas as palavras softwaredesign, software_design, software.design... e assim por diante tenham o mesmo número na coluna do mapa (neste caso específico, um número de 1 a 10). O mesmo se aplica à engenharia_civil e ao Desenho Industrial.
Eu sei que isso envolve algumas expressões regulares e comparações que não diferenciam maiúsculas de minúsculas, mas estou preso na lógica SQL. Eu sei que essas expressões podem ser úteis:
regexp_replace(word, '(\.|:|,|&|-)','','g')
Para lidar com os separadores
lower(something)
Para lidar com a correspondência de maiúsculas e minúsculas ou
UPDATE words_table SET a.map = b.id_word WHERE word ILIKE something
... WHERE word ~* something
para correspondência insensível a maiúsculas e minúsculas.
Devo criar novas colunas com palavras regexp_replaced e fazer o mapeamento depois disso com algumas junções? Ou talvez algo com CamelCase e correspondência de sublinhado? Talvez funções? Qual é a solução ótima?
Projeto de banco de dados
Ou você já tem a tabela de consulta e esqueceu de mencioná-la, ou deve criar uma.
Aqui e aqui
text
é porque eu normalmente prefirovarchar(n)
.É por isso que coloquei as duas
integer
colunas primeiro na tabelaword
.dados do mapa
Defina uma função como @Daniel já sugeriu .
Dependendo de seus requisitos exatos, eu usaria classes de caracteres predefinidas sempre que possível em uma expressão regular, em vez de lançar minhas próprias. O Postgres usa informações de localidade do seu sistema operacional para identificar caracteres, dígitos, etc.
é a negação, ou seja, todos os outros personagens.[:alnum:]
inclui todos os números e dígitos, dependendo da sua localidade. Ao contrário ,[a-zA-Z0-9]
isso também identificaä
oué
como caracteres - dependendo da sua localidade.Há também a abreviação de classe
\W
semelhante , mas isso incluiria o sublinhado_
.Esta atualização seria mais eficiente então:
Você pode dividi-lo em dois problemas menores.
Primeiro crie uma função que faça a simplificação da palavra. Esta versão apenas remove qualquer caractere não alfanumérico e define o resultado em letras minúsculas. Refine-o, se necessário.
Em seguida, atualize a
map
coluna juntando a tabela nela mesma, combinando cada palavra com sua versão "simplificada".Isso pressupõe que qualquer versão simplificada de uma palavra já faz parte da tabela, como parece ser o caso em seus dados de amostra. Caso contrário, eles devem ser inseridos.
Nos pequenos conjuntos de dados, você pode usar funções que calculam derivadas sempre que precisar delas, mas em grandes junções essa função será invocada para cada linha repetidas vezes. Isso pode diminuir o desempenho geral.
Mais eficiente é armazenar derivadas pré-calculadas. Uma maneira é armazená-los junto com as strings originais, mas você obterá um campo de baixa cardinalidade que precisa ser indexado. A outra abordagem é manter a tabela intermediária de derivadas usadas em junções para colar outras tabelas.