Related
I've tried to use CONCAT function of some fields in a table; in order to get a string that I need to compare onto another field from different table.
However when I use the function it's like it random adds spaces between the fields and then I cannot use this result to compare.
I've tried:
SELECT CONCAT([STC_GL-STC].[ZZGL_Desc_Group_5D],'-',
[STC_GL-STC].[ZZCostCentreGroup],'-',
AS RESULT
FROM [STC_GL-STC];
As an example of result:
'Compras - RM -MATERIA PRIMA -'
(Please note the blank spaces in the second and third (-).
I would need to obtain:
'Compras - RM-MATERIA PRIMA-'
I've checked the values in the fields and there is no blank spaces at the end on fields ZZGL_Desc_Group_5D , ZZCostCentreGroup.
I've also tried:
SELECT CONCAT_WS('-',[ZZGL_Desc_Group_5D],[ZZCostCentreGroup]) AS RESULT
FROM [STC_GL-STC]
With same result.
And finally I tried to remove blank spaces using RTRIM and LTRIM using the following:
SELECT CONCAT(LTRIM(RTRIM([STC_GL-STC].[ZZGL_Desc_Group_5D])),
LTRIM(RTRIM('-')),
LTRIM(RTRIM([STC_GL-STC].[ZZCostCentreGroup]))) AS RESULT
FROM [STC_GL-STC]
ORDER BY RESULT ASC;
And even with LTRIM and RTRIM functions on that field, I still getting the same result.
How to get rid of this behaviour and of the blank spaces? Is there another way to build that string?
Kind Regards and many thanks in advance,
Long time ago I created a udf function to remove white spaces.
It is based on the 'magic' of the XML xs:token data type.
udf
/*
1. All invisible TAB, Carriage Return, and Line Feed characters will be replaced with spaces.
2. Then leading and trailing spaces are removed from the value.
3. Further, contiguous occurrences of more than one space will be replaced with a single space.
*/
CREATE FUNCTION dbo.udf_tokenize(#input VARCHAR(MAX))
RETURNS VARCHAR(MAX)
AS
BEGIN
RETURN (SELECT CAST('<r><![CDATA[' + #input + ']]></r>' AS XML).value('(/r/text())[1] cast as xs:token?','VARCHAR(MAX)'));
END
Test harness
-- DDL and sample data population, start
DECLARE #mockTbl TABLE (ID INT IDENTITY(1,1), col_1 VARCHAR(100), col_2 VARCHAR(100));
INSERT INTO #mockTbl (col_1, col_2)
VALUES (' FL ', ' Miami')
, (' FL ', ' Fort Lauderdale ')
, (' NY ', ' New York ')
, (' NY ', '')
, (' NY ', NULL);
-- DDL and sample data population, end
SELECT *
, col_1n = dbo.udf_tokenize(col_1)
, col_2n = dbo.udf_tokenize(col_2)
, CONCAT_WS('-', dbo.udf_tokenize(col_1), dbo.udf_tokenize(col_2)) AS RESULT
FROM #mockTbl;
I searched through many of the questions here but all I found with decent answer is for different language like Javascript etc.
I have a simple task in SQL that I can't seem to find a simple way to do.
I just need to count the number of "words" inside a SQL string (a sentence). You can see why "words" is in quotes in my examples. The "words" are delimited by white space.
Sample sentences:
1. I am not your father.
2. Where are your brother,sister,mother?
3. Where are your brother, sister and mother?
4. Who are you?
Desired answer:
1. 5
2. 4
3. 7
4. 3
As you can see, I need to count the "words" disregarding the symbols (I have to treat them as part of the word). So in sample no. 2:
(1)Where (2)are (3)your (4)brother,sister,mother? = 4
I can handle the multiple whitespaces by doing a replace like this:
REPLACE(string, ' ', ' ') -> 2 whitespaces to 1
REPLACE(string, ' ', ' ') -> 3 whitespaces to 1 and so on..
What SQL function can I use to do this? I use SQL Server 2012 but needs a function that works in SQL Server 2008 as well.
Here is one way to do it:
Create and populate sample table (Please save is this step in your future questions)
DECLARE #T AS TABLE
(
id int identity(1,1),
string varchar(100)
)
INSERT INTO #T VALUES
('I am not your father.'),
('Where are your brother,sister,mother?'),
('Where are your brother, sister and mother?'),
('Who are you?')
Use a cte to replace multiple spaces to a single space (Thanks to Gordon Linoff's answer here)
;WITH CTE AS
(
SELECT Id,
REPLACE(REPLACE(REPLACE(string, ' ', '><' -- Note that there are 2 spaces here
), '<>', ''
), '><', ' '
) as string
FROM #T
)
Query the CTE - length of the string - length of the string without spaces + 1:
SELECT id, LEN(string) - LEN(REPLACE(string, ' ', '')) + 1 as CountWords
FROM CTE
Results:
id CountWords
1 5
2 4
3 7
4 3
This is a minor improvement of #ZoharPeled's answer. This can also handle 0 length values:
DECLARE #t AS TABLE(id int identity(1,1), string varchar(100))
INSERT INTO #t VALUES
('I am not your father.'),
('Where are your brother,sister,mother?'),
('Where are your brother, sister and mother?'),
('Who are you?'),
('')
;WITH CTE AS
(
SELECT
Id,
REPLACE(REPLACE(string,' ', '><'), '<>', '') string
FROM #t
)
SELECT
id,
LEN(' '+string)-LEN(REPLACE(string, '><', ' ')) CountWords
FROM CTE
To handle multiple spaces too, use the method shown here
Declare #s varchar(100)
set #s='Who are you?'
set #s=ltrim(rtrim(#s))
while charindex(' ',#s)>0
Begin
set #s=replace(#s,' ',' ')
end
select len(#s)-len(replace(#s,' ',''))+1 as word_count
https://exploresql.com/2018/07/31/how-to-count-number-of-words-in-a-sentence/
I found this query more useful than the first. it omit extra characters and numbers and symbols, so it would count just words within a passage...
drop table if exists #t
create table #t (id int identity(1,1), c1 varchar(2000))
insert into #t (c1)
values
('Alireza Sattarzadeh Farkoush '),
('yes it is the best .'),
('abc def ghja a the . asw'),
('?>< 123 ...! z a b'),
('Wallex is the greatest exchange in the .. world a after binance ...!')
select c1 , Count(*)
from (
select id, c1, value
from #t t
cross apply (
select rtrim(ltrim(value)) as value from string_split(c1,' ')) a
where len(value) > 1 and value like '%[a-Z]%'
) Final
group by c1
I have one column for comment and I need to show this for one report.
Here what happen some time, users uses multiple enters in comment box. I can not access code part I need to manage this thing in SQL only.
So I have removed unwanted
1 /r/n
2 /n/n
from using
REPLACE(REPLACE(Desc, CHAR(13)+CHAR(10), CHAR(10)),CHAR(10)+CHAR(10), CHAR(10)) as Desc,
Now I want to remove any \r or \n from starting or ending of the string if any
By the way you meant in your question:(Remove char(10) or char(13) from specific string)
Note: You should see the output result by switching your resultset output to Results to Text(Ctrl+T).
Results to Text
Results to Grid
Use TRIM check here
Example : UPDATE tablename SET descriptions = TRIM(TRAILING "<br>" FROM descriptions)
if you want to replace newline then use something like below
SELECT REPLACE(REPLACE(#str, CHAR(13), ''), CHAR(10), '')
or
DECLARE #testString varchar(255)
set #testString = 'MY STRING '
/*Select the string and try to copy and paste into notepad and tab is still there*/
SELECT testString = #testString
/*Ok, it seems easy, let's try to trim this. Huh, it doesn't work, the same result here.*/
SELECT testStringTrim = RTRIM(#testString)
/*Let's try to get the size*/
SELECT LenOfTestString = LEN(#testString)
/*This supposed to give us string together with blank space, but not for tab though*/
SELECT DataLengthOfString= DATALENGTH(#testString)
SELECT ASCIIOfTab = ASCII(' ')
SELECT CHAR(9)
/*I always use this like a final solution*/
SET #testString = REPLACE(REPLACE(REPLACE(#testString, CHAR(9), ''), CHAR(10), ''), CHAR(13), '') SELECT #testString
/*
CHAR(9) - Tab
CHAR(10) - New Line
CHAR(13) - Carriage Return
*/
Reference
select dbo.trim('abc','c') -- ab
select dbo.trim('abc','a') -- bc
select dbo.trim(' b ',' ') -- b
Create a user-define-function: trim()
trim from both sides
trim any letter: space, \r, \n, etc
Create FUNCTION Trim
(
#Original varchar(max), #letter char(1)
)
RETURNS varchar(max)
AS
BEGIN
DECLARE #rtrim varchar(max)
SELECT #rtrim = iif(right(#original, 1) = #letter, left(#original,datalength(#original)-1), #original)
return iif( left(#rtrim,1) = #letter, right(#rtrim,datalength(#rtrim)-1),#rtrim)
END
This is in SQL Server 2005. I have a varchar column and some rows contain trailing space, e.g. abc, def.
I tried removing the trailing space with this command:
update thetable
set thecolumn = rtrim(thecolumn)
But the trailing space remains. I tried to find them using:
select *
from thetable
where thecolumn <> rtrim(thecolumn)
But it returned nothing.
Are there some settings that I am not aware that influences trailing space check?
EDIT:
I know that there is trailing space from SSMS, when I copy paste the value from the grid to the editor, it has trailing space.
Check if the spaces that are not removed have the ASCII code 32.
Try this to replace "hard space" with "soft space":
update thetable set thecolumn = rtrim(replace(thecolumn, char(160), char(32)))
the query was missing equal sign
Are you certain that it is a space (ascii 32) character? You can get odd behavior with other "non-visible" characters. Try running
select ascII(right(theColumn, 1))
from theTable
and see what you get.
Use this Function:
Create Function [dbo].[FullTrim] (#strText varchar(max))
Returns varchar(max) as
Begin
Declare #Ch1 char,#ch2 char
Declare #i int,#LenStr int
Declare #Result varchar(max)
Set #i=1
Set #LenStr=len(#StrText)
Set #Result=''
While #i<=#LenStr
Begin
Set #ch1=SUBSTRING(#StrText,#i,1)
Set #ch2=SUBSTRING(#StrText,#i+1,1)
if ((#ch1=' ' and #ch2=' ') or (len(#Result)=0 and #ch1=' '))
Set #i+=1
Else
Begin
Set #Result+=#Ch1
Set #i+=1
End
End
Return #Result
End
In SQL, CHAR(n) columns are right-padded with spaces to their length.
Also string comparison operators (and most functions too) do not take the trailing spaces into account.
DECLARE #t TABLE (c CHAR(10), vc VARCHAR(10))
INSERT
INTO #t
VALUES ('a ', 'a ')
SELECT LEN(c), LEN(vc), с + vc
FROM #t
--
1 1 "a a"
Please run this query:
SELECT *
FROM thetable
WHERE thecolumn + '|' <> RTRIM(thecolumn) + '|'
and see if it finds something.
It sounds like either:
1) Whatever you are using to view the values is inserting the trailing space (or the appearance thereof- try a fixed-width font like Consolas).
2) The column is CHAR, not VARCHAR. In that case, the column will be padded with spaces up to the length of the column, e.g. inserting 'abc' into char(4) will always result in 'abc '
3) You are somehow not committing the updates, not updating the right column, or other form of user error. The update statement itself looks correct on the face of it.
I had the same issues with RTRIM() AND LTRIM() functions.
In my situation the problem was in LF and CR chars.
Solution
DECLARE #test NVARCHAR(100)
SET #test = 'Declaration status '
SET #test = REPLACE(REPLACE(#test, CHAR(10), ''), CHAR(13), '')
I need to ensure that a given field does not have more than one space (I am not concerned about all white space, just space) between characters.
So
'single spaces only'
needs to be turned into
'single spaces only'
The below will not work
select replace('single spaces only',' ',' ')
as it would result in
'single spaces only'
I would really prefer to stick with native T-SQL rather than a CLR based solution.
Thoughts?
Even tidier:
select string = replace(replace(replace(' select single spaces',' ','<>'),'><',''),'<>',' ')
Output:
select single spaces
This would work:
declare #test varchar(100)
set #test = 'this is a test'
while charindex(' ',#test ) > 0
begin
set #test = replace(#test, ' ', ' ')
end
select #test
If you know there won't be more than a certain number of spaces in a row, you could just nest the replace:
replace(replace(replace(replace(myText,' ',' '),' ',' '),' ',' '),' ',' ')
4 replaces should fix up to 16 consecutive spaces (16, then 8, then 4, then 2, then 1)
If it could be significantly longer, then you'd have to do something like an in-line function:
CREATE FUNCTION strip_spaces(#str varchar(8000))
RETURNS varchar(8000) AS
BEGIN
WHILE CHARINDEX(' ', #str) > 0
SET #str = REPLACE(#str, ' ', ' ')
RETURN #str
END
Then just do
SELECT dbo.strip_spaces(myText) FROM myTable
This is somewhat brute force, but will work
CREATE FUNCTION stripDoubleSpaces(#prmSource varchar(max)) Returns varchar(max)
AS
BEGIN
WHILE (PATINDEX('% %', #prmSource)>0)
BEGIN
SET #prmSource = replace(#prmSource ,' ',' ')
END
RETURN #prmSource
END
GO
-- Unit test --
PRINT dbo.stripDoubleSpaces('single spaces only')
single spaces only
update mytable
set myfield = replace (myfield, ' ', ' ')
where charindex(' ', myfield) > 0
Replace will work on all the double spaces, no need to put in multiple replaces. This is the set-based solution.
It can be done recursively via the function:
CREATE FUNCTION dbo.RemSpaceFromStr(#str VARCHAR(MAX)) RETURNS VARCHAR(MAX) AS
BEGIN
RETURN (CASE WHEN CHARINDEX(' ', #str) > 0 THEN
dbo.RemSpaceFromStr(REPLACE(#str, ' ', ' ')) ELSE #str END);
END
then, for example:
SELECT dbo.RemSpaceFromStr('some string with many spaces') AS NewStr
returns:
NewStr
some string with many spaces
Or the solution based on method described by #agdk26 or #Neil Knight (but safer)
both examples return output above:
SELECT REPLACE(REPLACE(REPLACE('some string with many spaces'
, ' ', ' ' + CHAR(7)), CHAR(7) + ' ', ''), ' ' + CHAR(7), ' ') AS NewStr
--but it remove CHAR(7) (Bell) from string if exists...
or
SELECT REPLACE(REPLACE(REPLACE('some string with many spaces'
, ' ', ' ' + CHAR(7) + CHAR(7)), CHAR(7) + CHAR(7) + ' ', ''), ' ' + CHAR(7) + CHAR(7), ' ') AS NewStr
--but it remove CHAR(7) + CHAR(7) from string
How it works:
Caution:
Char/string used to replace spaces shouldn't exist on begin or end of string and stand alone.
Here is a simple function I created for cleaning any spaces before or after, and multiple spaces within a string. It gracefully handles up to about 108 spaces in a single stretch and as many blocks as there are in the string. You can increase that by factors of 8 by adding additional lines with larger chunks of spaces if you need to. It seems to perform quickly and has not caused any problems in spite of it's generalized use in a large application.
CREATE FUNCTION [dbo].[fnReplaceMultipleSpaces] (#StrVal AS VARCHAR(4000))
RETURNS VARCHAR(4000)
AS
BEGIN
SET #StrVal = Ltrim(#StrVal)
SET #StrVal = Rtrim(#StrVal)
SET #StrVal = REPLACE(#StrVal, ' ', ' ') -- 16 spaces
SET #StrVal = REPLACE(#StrVal, ' ', ' ') -- 8 spaces
SET #StrVal = REPLACE(#StrVal, ' ', ' ') -- 4 spaces
SET #StrVal = REPLACE(#StrVal, ' ', ' ') -- 2 spaces
SET #StrVal = REPLACE(#StrVal, ' ', ' ') -- 2 spaces (for odd leftovers)
RETURN #StrVal
END
Method #1
The first method is to replace extra spaces between words with an uncommon symbol combination as a temporary marker. Then you can replace the temporary marker symbols using the replace function rather than a loop.
Here is a code example that replaces text within a String variable.
DECLARE #testString AS VARCHAR(256) = ' Test text with random* spacing. Please normalize this spacing!';
SELECT REPLACE(REPLACE(REPLACE(#testString, ' ', '*^'), '^*', ''), '*^', ' ');
Execution Time Test #1: In ten runs of this replacement method, the average wait time on server replies was 1.7 milliseconds and total execution time was 4.6 milliseconds.
Execution Time Test #2: The average wait time on server replies was 1.7 milliseconds and total execution time was 3.7 milliseconds.
Method #2
The second method is not quite as elegant as the first, but also gets the job done. This method works by nesting four (or optionally more) replace statements that replace two blank spaces with one blank space.
DECLARE #testString AS VARCHAR(256) = ' Test text with random* spacing. Please normalize this spacing!';
SELECT REPLACE(REPLACE(REPLACE(REPLACE(#testString,' ',' '),' ',' '),' ',' '),' ',' ')
Execution Time Test #1: In ten runs of this replacement method, the average wait time on server replies was 1.9 milliseconds and total execution time was 3.8 milliseconds.
Execution Time Test #2: The average wait time on server replies was 1.8 milliseconds and total execution time was 4.8 milliseconds.
Method #3
The third method of replacing extra spaces between words is to use a simple loop. You can do a check on extra spaces in a while loop and then use the replace function to reduce the extra spaces with each iteration of the loop.
DECLARE #testString AS VARCHAR(256) = ' Test text with random* spacing. Please normalize this spacing!';
WHILE CHARINDEX(' ',#testString) > 0
SET #testString = REPLACE(#testString, ' ', ' ')
SELECT #testString
Execution Time Test #1: In ten runs of this replacement method, the average wait time on server replies was 1.8 milliseconds and total execution time was 3.4 milliseconds.
Execution Time Test #2: The average wait time on server replies was 1.9 milliseconds and total execution time was 2.8 milliseconds.
This is the solution via multiple replace, which works for any strings (does not need special characters, which are not part of the string).
declare #value varchar(max)
declare #result varchar(max)
set #value = 'alpha beta gamma delta xyz'
set #result = replace(replace(replace(replace(replace(replace(replace(
#value,'a','ac'),'x','ab'),' ',' x'),'x ',''),'x',''),'ab','x'),'ac','a')
select #result -- 'alpha beta gamma delta xyz'
You can try this:
select Regexp_Replace('single spaces only','( ){2,}', ' ') from dual;
Just Adding Another Method-
Replacing Multiple Spaces with Single Space WITHOUT Using REPLACE in SQL Server-
DECLARE #TestTable AS TABLE(input VARCHAR(MAX));
INSERT INTO #TestTable VALUES
('HAPPY NEWYEAR 2020'),
('WELCOME ALL !');
SELECT
CAST('<r><![CDATA[' + input + ']]></r>' AS XML).value('(/r/text())[1] cast as xs:token?','VARCHAR(MAX)')
AS Expected_Result
FROM #TestTable;
--OUTPUT
/*
Expected_Result
HAPPY NEWYEAR 2020
WELCOME ALL !
*/
Found this while digging for an answer:
SELECT REPLACE(
REPLACE(
REPLACE(
LTRIM(RTRIM('1 2 3 4 5 6'))
,' ',' '+CHAR(7))
,CHAR(7)+' ','')
,CHAR(7),'') AS CleanString
where charindex(' ', '1 2 3 4 5 6') > 0
The full answer (with explanation) was pulled from: http://techtipsbysatish.blogspot.com/2010/08/sql-server-replace-multiple-spaces-with.html
On second look, seems to be just a slightly different version of the selected answer.
Please Find below code
select trim(string_agg(value,' ')) from STRING_SPLIT(' single spaces only ',' ')
where value<>' '
This worked for me..
Hope this helps...
With the "latest" SQL Server versions (Compatibility level 130) you could also use string_split and string_agg.
string_split can return an ordinal column when provided with a third argument. (https://learn.microsoft.com/en-us/sql/t-sql/functions/string-split-transact-sql?view=sql-server-ver16#enable_ordinal). So we can preserve the order of the string_split.
Using a common table expression:
with cte(value) as (select value from string_split(' a b c d e ', ' ', 1) where value <> '' order by ordinal offset 0 rows)
select string_agg(value, ' ') from cte
a b c d e results in a b c d e
I use FOR XML PATH solution to replace multiple spaces into single space
The idea is to replace spaces with XML tags
Then split XML string into string fragments without XML tags
Finally concatenating those string values by adding single space characters between two
Here is how final UDF function can be called
select dbo.ReplaceMultipleSpaces(' Sample text with multiple space ')