Строка усекается по длине, но не разрезание слов разрешено
Я хочу ограничить длину поля строки в MYSQL на определенную длину, но я не хочу, чтобы какие-либо измельчения слов возникали.
Когда я это сделаю:
SELECT SUBSTRING('Business Analist met focus op wet- en regelgeving', 1, 28)
Я получаю это как вывод:
Business Analist met focus o
Но я хотел бы
Business Analist met focus
Как я могу ввести ограничение в 28 символов, но не прерывать слова? Конечно, легко [вставить язык программирования здесь];-), но я хочу знать, возможно ли это в MYSQL в простой инструкции.
Ответы
Ответ 1
Пусть @str
будет вашей строкой и @len
начальная позиция, на которую нужно нарезать. Затем необходимыми шагами могут быть:
-
Возьмите самые левые символы @len
@str
.
-
Отмените подстроку.
-
Найдите позицию первого пространства в обратной подстроке.
-
Вычитайте 1
из позиции. Но если пространство не найдено, пусть позиция остается 0
.
-
Вычтите найденную позицию из @len
и назовите ее cutpos
.
-
Возьмите первые (самые левые) cutpos
символы @str
как str1
, возьмите все остальные символы (начиная с cutpos+1
) как str2
.
SELECT
LEFT(str, cutpos) AS str1,
SUBSTRING(str, cutpos + 1) AS str2
FROM (
SELECT
@str AS str,
@len - IFNULL(NULLIF(LOCATE(' ', REVERSE(LEFT(@str, @len))), 0) - 1, 0) AS cutpos
) s
Ответ 2
Как насчет разбиения на пробелы:
SELECT SUBSTRING_INDEX('Business Analist met focus op wet- en regelgeving',' ',4)
вернет
Business Analist met focus
Ответ 3
Очень интересная проблема. Вот как я это сделал:
//gets initial string - use 29 instead of 28 to see if the 29th character is a space
SELECT SUBSTRING('Business Analist met focus op wet- en regelgeving', 1, 29)
//inverts the string, so we can get the first
SELECT REVERSE( SUBSTRING('Business Analist met focus op wet- en regelgeving', 1, 29))
// find the charindex of the first space (last space in the string not reversed)
SELECT CHARINDEX(' ', REVERSE( SUBSTRING('Business Analist met focus op wet- en regelgeving', 1, 29)))
// get the substring from the first (last) space
SELECT SUBSTRING(REVERSE( SUBSTRING('Business Analist met focus op wet- en regelgeving', 1, 29)), CHARINDEX(' ', REVERSE( SUBSTRING('Business Analist met focus op wet- en regelgeving', 1, 29))), 29)
// reverse the string again to unfold it.
SELECT REVERSE(SUBSTRING(REVERSE( SUBSTRING('Business Analist met focus op wet- en regelgeving', 1, 29)), CHARINDEX(' ', REVERSE( SUBSTRING('Business Analist met focus op wet- en regelgeving', 1, 29))), 29))
// to try different lengths...
DECLARE @size int
select @size = 24
SELECT REVERSE(SUBSTRING(REVERSE( SUBSTRING('Business Analist met focus op wet- en regelgeving', 1, @size)),
CHARINDEX(' ', REVERSE( SUBSTRING('Business Analist met focus op wet- en regelgeving', 1, @size))), @size))
Ответ 4
В SQL это будет...
select Substring('Business Analist met focus op wet- en regelgeving', 0 , 28 + 2 - CharIndex(' ', REVERSE(SUBSTRING('Business Analist met focus op wet- en regelgeving', 0, 28 + 1 )),0))
Я не знаю, доступны ли все эти функции в MYSQL
EDIT: Я думаю, что для MYSQL замените "Locate" на "CharIndex"
Ответ 5
Настройте ответ на Нарни, здесь, который работает с двумя полями (a.product, a.descr) и где "..." добавляется, когда строка усечена. a.descr также может быть пустым.
IF (
CHARACTER_LENGTH(
IF(
a.descr = '',
a.product,
CONCAT_WS(' - ',a.product,a.descr)
)
)>35,
IF(
a.descr = '',
CONCAT(
REVERSE(SUBSTRING(REVERSE( SUBSTRING(a.product, 1, 35)), locate(' ', REVERSE( SUBSTRING(a.product, 1, 35))), 35)),
'...'
),
CONCAT(
REVERSE(SUBSTRING(REVERSE( SUBSTRING(CONCAT_WS(' - ',a.product,a.descr), 1, 35)), locate(' ', REVERSE( SUBSTRING(CONCAT_WS(' - ',a.product,a.descr), 1, 35))), 35)),
'...'
)
),
CONCAT_WS(' - ',a.product,a.descr)
)
Мне нужно было что-то вроде этого, поэтому я добавил его. Может помочь кому-то другому.
Ответ 6
@Андрей Андреевич. Мне очень понравился ваш ответ:)
Во всяком случае, я нахожусь на моем db, он работает лучше, если вы меняете строки 2 и 3 следующим образом:
SELECT
IF(LENGTH(str)<[email protected],str,LEFT(str, cutpos)) AS str1,
IF(LENGTH(str)<[email protected],'',SUBSTRING(str, cutpos + 1)) AS str2
FROM (
SELECT
@str AS str,
@len - IFNULL(NULLIF(LOCATE(' ', REVERSE(LEFT(@str, @len))), 0) - 1, 0) AS cutpos
FROM @table
) s
Не знаю, была ли это моя ошибка или что, но, наоборот, она иногда усекала строки в первой букве, когда их длина была < @len, то есть "First s" - "tring" вместо "First" "строка", когда @len = 13
Я отправлю вам рабочий пример:
CREATE TABLE `test` (
`sometext` varchar(65)
);
INSERT INTO `test` (`sometext`) VALUES
('Firs strin'),
('Alll right'),
('third string'),
('fourth string'),
('a longer example string'),
('Supercalifragilisticexpialidocious');
SELECT
IF(LENGTH(str)<=12,str,LEFT(str, cutpos)) AS str1,
IF(LENGTH(str)<=12,'',SUBSTRING(str, cutpos + 1)) AS str2
FROM (
SELECT
sometext AS str,
12 - IFNULL(NULLIF(LOCATE(' ', REVERSE(LEFT(sometext, 12))), 0) - 1, 0) AS cutpos
FROM test
) s
И вот пример неработающий с использованием исходного кода:
SELECT
LEFT(str, cutpos) AS str1,
SUBSTRING(str, cutpos + 1) AS str2
FROM (
SELECT
sometext AS str,
12 - IFNULL(NULLIF(LOCATE(' ', REVERSE(LEFT(sometext,12))), 0) - 1, 0) AS cutpos
FROM test
) s
Я не уверен, что это проблема utf8, или я просто неверно истолковал ваш код или что еще...
Ответ 7
Похоже, люди не читают руководство по mysql:
Оригинал: SELECT SUBSTRING('Business Analist met focus op wet- en regelgeving', 1, 28)
дает сломанные слова.
Изменено: SELECT SUBSTRING_INDEX('Business Analist met focus op wet- en regelgeving', ' ' , 4)
дает несломанные слова
SUBSTRING_INDEX(string, delimiter, number)
будет усекать строку по количеству разграничителей.
Сделайте свой разделитель пространством, и вы получите только целые слова. так:
SUBSTRING_INDEX( LEFT('Business Analist met focus op wet- en regelgeving',28), ' ' , 4)
должен это сделать.