Как вставить пробел перед 2-й заглавной буквой строки в MySQL? - PullRequest
0 голосов
/ 05 февраля 2019

У меня есть некоторые данные от стороннего производителя, и один столбец представляет собой объединение имени и фамилии, но между ними нет пробела.Моя цель - вставить пробел перед второй заглавной буквой, например:

some_name
-------------
AdamPeterson
JohnSmith
StevenMulroy

станет:

some_name
-------------
Adam Peterson
John Smith
Steven Mulroy

Я знаю, что это не надежно, но лучше всего этособираюсь получить исходные данные, которые у меня есть.

Мне нужно делать это в SQL, а не в Excel и т. д., поскольку данные регулярно обновляются на уровне базы данных, а затем обрабатываются другой системой без предварительногоэкспортируется.

Любая помощь с благодарностью!

Ответы [ 2 ]

0 голосов
/ 05 февраля 2019

Здесь приведен общий запрос для всех версий MySQL 5.1+, который, безусловно, будет работать и на MariaDB.Общая идея заключается в использовании генератора чисел MySQL для разделения строки на «токены» и проверки диапазона ascii, является ли «токен» заглавной буквой или нет

Запрос

SELECT 
   names.name   
 ,  INSERT (
       names.name 
     , LOCATE(
           SUBSTRING(names.name, number_generator.number, 1)  
         , names.name   
       )
     , 1
     , CONCAT(' ', SUBSTRING(names.name, number_generator.number, 1))
   ) AS changed_name
FROM (
  SELECT 
    @row := @row + 1 AS number 
  FROM (
    SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT   6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
) row1
  CROSS JOIN (
  SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
) row2
CROSS JOIN (
  SELECT @row := 0 
) init_user_params 
) AS number_generator
CROSS JOIN 
 names 
WHERE
   number_generator.number > 1
 AND
   ASCII(SUBSTRING(names.name, number_generator.number, 1)) BETWEEN 65 AND 90

Результат

| name         | changed_name  |
| ------------ | ------------- |
| AdamPeterson | Adam Peterson |
| JohnSmith    | John Smith    |
| StevenMulroy | Steven Mulroy |

см. демо

Примечание

Этот запросне будет хорошо масштабироваться для (очень) больших таблиц с миллионами или даже миллиардами записей, потому что вы можете использовать CROSS JOIN

или использовать метод без таблиц с

CROSS JOIN ( SELECT 'AdamPeterson' AS name UNION SELECT 'JohnSmith' UNION SELECT 'StevenMulroy' ) AS names

видите, что демо

Или используйте партии, когда у вас большие столы

CROSS JOIN ( SELECT name FROM names WHERE id >= 1 AND id <= 2 ORDER BY names.id ASC<br> ) AS names

Почему нет LIMIT?LIMIT медленно при использовании с большими числами смещения, такими как LIMIT 1000000, 1000.MySQL необходимо извлечь 1001000 записей и снова удалить 1000000 записей из временной таблицы (диск в худшем случае)

. demo

Отредактировано

для меня все это похоже на черную магию!Это почти идеально - попробуйте названия «AlexLafferty» или «LaurenAnderson».Может быть, одна ошибка или что-то на А?Спасибо за вашу помощь!

После обзора я заметил, что использование LOCATE(..) в INSERT(..) довольно избыточно и может быть удалено для правильной работы.

Так что патч

SELECT 
    names.name   
 ,  INSERT (
       names.name 
     , number_generator.number
     , 1
     , CONCAT(' ', SUBSTRING(names.name, number_generator.number, 1))
   ) AS changed_name

см. демо

0 голосов
/ 05 февраля 2019

Для Mysql 8

SELECT REGEXP_REPLACE(CAST('JohnLexxxanon' as BINARY), '^([A-Z][a-z]+)([A-Z][a-z]+)$', '$1 $2');

Для MariaDb 10 +

SELECT REGEXP_REPLACE(CAST('JohnLexxxanon' as BINARY), '^([A-Z][a-z]+)([A-Z][a-z]+)$', '\\1 \\2');

Данные преобразуются в двоичный файл для достижения чувствительности к регистру.

Это работает для MySql 8 иMariaDb 10 +

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...