Как объединить имя, отчество и фамилию, где имя посредника либо пустое, либо пустое

#sql #sql-server #tsql

Вопрос:

Я пытаюсь объединить имя, фамилию и среднее имя с помощью SQL Server.

SQL, который я пытаюсь использовать, это:

 SELECT REPLACE(CONCAT_WS(' ',FirstName,MiddleName,LastName),'  ',' ') AS Name
FROM dbo.address
 

Но в некоторых случаях этот запрос дает мне странный вывод:

Вот примеры данных в моем случае использования.

имя промежуточное имя фамилия
Джон нулевой Лапп
Джон Лапп
Джон Лапп
Счета нулевой Подлежащий уплате
Счета Подлежащий уплате
Счета Подлежащий уплате
Счета нулевой Подлежащий уплате

Но в выходных данных есть еще одно дополнительное пространство, name когда промежуточное имя пусто. Извините за скриншот для вывода.

введите описание изображения здесь

Но в другом случае с тем же типом данных, где среднее имя равно null или пусто, он выдает правильный вывод, что означает, что между именем нет дополнительного пространства, когда среднее имя является пустой строкой.

введите описание изображения здесь

Попробовав ответить на этот вопрос, я получил еще один странный результат.

введите описание изображения здесь

Комментарии:

1. В соответствии с руководством по вопросам, пожалуйста, не размещайте изображения кода, данных, сообщений об ошибках и т.д. — Скопируйте или введите текст в вопрос. Пожалуйста, зарезервируйте использование изображений для диаграмм или демонстрации ошибок рендеринга, вещей, которые невозможно точно описать с помощью текста.

Ответ №1:

Эта CONCAT_WS функция творит свое волшебство. Проблема в том, что у вас есть либо пустая строка, либо один пробел для некоторых значений среднего имени в определенных записях. По праву, пропущенные отчества должны быть всегда NULL . Вот один обходной путь:

 SELECT
    CONCAT_WS(' ', FirstName,
                   CASE WHEN MiddleName NOT IN ('', ' ') THEN MiddleName END,
                   LastName) AS Name
FROM dbo.address;
 

Логика здесь состоит в том , чтобы заменить пустую строку или отчество с одним пробелом NULL на, тем самым позволяя CONCAT_WS игнорировать его.

Комментарии:

1. Я бы предложил добавить ISNULL в инструкцию case, чтобы также обрабатывать значения NULL

2. @JayasuryaSatheesh Не нужно. CONCAT_WS уже является безопасным значением null и будет игнорировать NULL значения.

3. @TimBiegeleisen Я попробовал ваш ответ и снова получил другой результат в нулевых случаях. который я добавил в качестве скриншота в вопросе.

4. Тогда, возможно, у первого имени есть завершающий пробел или фамилия, ведущая пробел. Похоже, мой ответ работает для некоторых пустых отчеств, но не для всех. На данный момент я бы заподозрил данные.

5. @TimBiegeleisen это выглядит нормально с глазами, но я не понимаю, как проверить это программно.

Ответ №2:

 select FName ' '  IsNull(NullIf(MName   ' ',''),'')   LName
from tblName
 

введите описание изображения здесь

Ответ №3:

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

 select concat_ws(' ', trim(firstname), isnull(trim(middlename), ''), trim(lastname)),
  from src_data;
 

Но trim(‘ ‘) возвращает пустой символ, который не является нулевым, и из документов

«CONCAT_WS игнорирует нулевые значения во время объединения и не добавляет разделитель между нулевыми значениями».

Это означает, что concat_ws вернется

исходная запись Результат
«Джон — нуль — Доу» «Джон — космический неизвестный»
«Джон — пустой символ — Доу «Джон — спейс спейс — Доу»

Итак, все, что осталось, — это преобразовать все пустые символы в нули

 select concat_ws(' ', trim(firstname), replace(trim(middlename), '', null), trim(lastname))
  from src_data;
 

Я сделал это для второго имени, но, поскольку пользовательский ввод определенно не был должным образом очищен, я бы сделал это и для имени и фамилии

Вот что такое dbfiddle