#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:
Ответ №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