Split string no MySQL

O MySQL não tem uma função para quebrar strings separadas por um determinado caractere (vírgula, por exemplo). A maioria das soluções que encontrei na web são baseadas em procedures. Não satisfeito com essa opção, fiz alguns estudos e cheguei à seguinte query:

SELECT DISTINCT 
SUBSTRING_INDEX(SUBSTRING_INDEX('1,2,3,4,5', ',', `i`), ',', -1) AS `val` 
FROM (
  SELECT @n := @n + 1 AS `i` 
  FROM `huge_table`, (SELECT @n := 0) `a` LIMIT 999
) `b`

Explicando:

  1. Geramos uma lista com valores de 1 até 999 (SELECT @n := @n + 1 AS `i` FROM `huge_table`, (SELECT @n := 0) `n` LIMIT 999). Aqui `huge_table` deve ser substituído pelo nome de uma tabela que tenha o número de registros (linhas) no mínimo igual ao valor especificado na cláusula LIMIT.
  2. Em seguida usamos esses valores no sequência de funções SUBSTRING_INDEX para extrair os valores da string.

Obs.: Você pode usar um valor menor (ou maior) no LIMIT se souber que a sua lista tem sempre menos (ou mais) valores.

Advertisements

5 thoughts on “Split string no MySQL

    1. Daniel, com certeza função (ou procedure) é o caminho mais óbvio e simples em situações como essa. No caso do banco em que estava trabalhando quando escrevi o post, não tínhamos essas funcionalidades disponíveis, então acabamos nessa solução usando apenas uma query. Mas obrigado pelo link! Acho que pode ajudar muita gente que tenha acesso à escrita de funções e chegue até aqui.

  1. Gustavo, parabéns! Gostei muito da sua query e gostaria de usá-la. Só que o meu problema é que eu tenho uma tabela com uma coluna, que pode ter n id’s assim, isto é, no voo não sei o conteúdo da coluna nem quantos elementos ela possui (pode 1 ou mais).
    Como eu poderia aplicar isso?

    1. César, se entendi corretamente, você pode aplicar a query da forma como ela está, apenas substituindo a string ‘1,2,3,4,5’ pela coluna que você deseja “quebrar” e fazendo um JOIN com a tabela que contém os valores, como a seguir:

      SELECT DISTINCT 
      SUBSTRING_INDEX(SUBSTRING_INDEX(`d`.`field_to_explode`, ',', `i`), ',', -1) AS `val` 
      FROM (
        SELECT @n := @n + 1 AS `i` 
        FROM `huge_table`, (SELECT @n := 0) `a` LIMIT 999
      ) `b` 
      INNER JOIN `data_table` `d`;

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s