select data up to a space? - sql-server

I have an MSSQL database field that looks like the examples below:
u129 james
u300 chris
u300a jim
u202 jane
u5 brian
u5z brian2
Is there a way to select the first set of characters? Basically select all the characters up until the first line space?
I tried messing around with LEFT, RIGHT, LEN, but couldn't figure out a way to do it with variable string lengths like in my example.
Thanks!

You can use a combiation of LEFT and CHARINDEX to find the index of the first space, and then grab everything to the left of that.
SELECT LEFT(YourColumn, charindex(' ', YourColumn) - 1)
And in case any of your columns don't have a space in them:
SELECT LEFT(YourColumn, CASE WHEN charindex(' ', YourColumn) = 0 THEN
LEN(YourColumn) ELSE charindex(' ', YourColumn) - 1 END)

select left(col, charindex(' ', col) - 1)

If the first column is always the same size (including the spaces), then you can just take those characters (via LEFT) and clean up the spaces (with RTRIM):
SELECT RTRIM(LEFT(YourColumn, YourColumnSize))
Alternatively, you can extract the second (or third, etc.) column (using SUBSTRING):
SELECT RTRIM(SUBSTRING(YourColumn, PreviousColumnSizes, YourColumnSize))
One benefit of this approach (especially if YourColumn is the result of a computation) is that YourColumn is only specified once.

An alternative if you sometimes do not have spaces do not want to use the CASE statement
select REVERSE(RIGHT(REVERSE(YourColumn), LEN(YourColumn) - CHARINDEX(' ', REVERSE(YourColumn))))
This works in SQL Server, and according to my searching MySQL has the same functions

If space is missing, you can add one
SELECT LEFT('YourTextOrColumn',
charindex(' ',
'YourTextOrColumn' + ' ') - 1 )

Related

Isolating String between 3 Characters

I have a view where I would like to create a column that isolates a string between 3 of the same character ("-"). So for example, I want AC-RBQ/4110-WS-L1 to become RBQ/4110.
So far I have tried this and it gets me very close.
SELECT SUBSTRING(locnum,CHARINDEX('-',locnum)+1,(((LEN(locnum))-CHARINDEX('-', REVERSE(locnum)))-CHARINDEX('-',locnum))) AS Result
Result:
RBQ/4110-WS
RBQ/4110-CS
I just need to remove that last "-WS" or "-CS"
Any thoughts or ideas would be greatly appreciated!
If the pattern is consistent, perhaps parsename() would be a good fit here
Example
Declare #S varchar(100) = 'AC-RBQ/4110-WS-L1'
Select parsename(replace(#S,'-','.'),3)
Returns
RBQ/4110
EDIT -
Just in case your data is more variable, you can use XML to extract the SECOND value
Example
Declare #YourTable table (locnum varchar(100))
Insert Into #YourTable values
('AC-RBQ/4110-WS-L1')
Select NewValue = convert(xml,'<x>'+replace(locnum,'-','</x><x>')+'</x>').value('/x[2]','varchar(100)')
From #YourTable
Returns
NewValue
RBQ/4110
It would seem simpler to split the value and then extract the 2nd item from your data. If your data always has 4 elements (and you always need the second), you could use PARSENAME:
SELECT PN.P
FROM (VALUES('AC-RBQ/4110-WS-L1'))V(S)
CROSS APPLY (VALUES(PARSENAME(REPLACE(V.S,'-','.'),3)))PN(P); --Part 3 as PARSENAME works right to left
Otherwise you could use a splitter like delimitedsplit8k_lead:
SELECT DS.Item
FROM (VALUES('AC-RBQ/4110-WS-L1'))V(S)
CROSS APPLY dbo.DelimitedSplit8K_lead(V.S,'-') DS
WHERE DS.ItemNumber = 2;
Please Try below Query. If your pattern is same per your question then below will work.
select left(SUBSTRING('AC-RBQ/4110-WS-L1', charindex('-','AC-RBQ/4110-WS-L1') + 1, LEN('AC-RBQ/4110-WS-L1')),8)
WITH TEMP AS
(
SELECT 'AC-RBQ/4110-WS-L1' AS COL
)
SELECT * ,
CHARINDEX('-', [COL]) AS FR,
CHARINDEX('-', [COL],CHARINDEX('-', [COL])+1) AS FR2,
SUBSTRING([COL], CHARINDEX('-', [COL]) +1 ,CHARINDEX('-', [COL],CHARINDEX('-
', [COL])+1) - (CHARINDEX('-', [COL]) +1) ) AS RESULT
FROM TEMP
You've done most of the work and you need to get the left part of the result up to -:
SELECT
LEFT(SUBSTRING(locnum, CHARINDEX('-', locnum) + 1,
(((LEN(locnum)) - CHARINDEX('-', REVERSE(locnum))) - CHARINDEX('-', locnum))),
CHARINDEX('-', SUBSTRING(locnum, CHARINDEX('-', locnum) + 1,
(((LEN(locnum)) - CHARINDEX('-', REVERSE(locnum))) - CHARINDEX('-', locnum)))) - 1) AS Result

SORTING THE string ROW having numeric values

I have a column with data like this:
COMPRESSIN 1(PB4),
COMPRESSIN 12(PB4),
COMPRESSIN 3(PB4).
I want to order the column by the COMPRESSION. So 1, 3, and 12 respectively as shown below:
COMPRESSION 1(PB4),
COMPRESSION 3(PB4),
COMPRESSION 12(PB4).
You need to order by a substring.
...
order by
substring(yourColumn,12,99)
This basically sorts on everything after 'COMPRESSION ' It's important to know that this is still sorting based on varchar order, which is using unicode decimal values. Thus, b comes before A due to it's case sensitivity, etc...
If your columns all end with the (XXX) pattern, you can use this to circumvent this.
order by
left(substring(yourColumn,12,99),len(substring(yourColumn,12,99)) - 5)
Another way you can do this is to remove the non-numeric portion while ordering:
ORDER BY CAST(
REPLACE(
REPLACE(YourColumn, 'COMPRESSION ','')
, '(PB4)','')
AS int) ASC
Here is a potential solution or at least one that can help put you in the right direction. I recommend you consider the clarity of your question and add more detail.
SELECT
ColumnName
FROM
TableName
ORDER BY
CAST(SUBSTRING(ColumnName, CHARINDEX(' ', ColumnName) + 1, CHARINDEX('(', ColumnName) - CHARINDEX(' ', ColumnName) - 1) AS int)
This works by using CHARINDEX to find the space after compression as a starting position (+1 to begin after the space) and the open parenthesis as the ending position to isolate the numeric value for sorting. You also need to convert this value to some type of numeric value like an integer.

SQL select to get a string between two spaces

I have a field with names in the format DOE JOHN HOWARD or DOE JOHN H.
I need a query to get the string between the two spaces (JOHN in this case).
The SO answer here shows how to do that when the desired substring is between two different strings, but I don't see how to apply something similar when the desired substring is between two instances of the same string (a space in this case).
How can I do that?
There is a somewhat sneaky way you could do this using PARSENAME.
It's intended purpose is to get particular parts of an object/namespace, however, in this case you could use it by replacing the strings with periods first.
E.g.,
SELECT PARSENAME(REPLACE('DOE JOHN HOWARD',' ','.'),2)
One way:
select
left(substring(fld,
charindex(' ', fld) + 1, len(fld)),
charindex(' ', substring(fld, charindex(' ', fld) + 2, len(fld))))
After doing some searches to resolve my problem, realised there is no generic answer, so below is piece of code to find string between some other strings. I think it may be useful for somebody in future.
DECLARE #STRING NVARCHAR(MAX) = 'Something here then stringBefore Searching stringAfter something there.'
DECLARE #FIRST NVARCHAR(20) = 'stringBefore'
DECLARE #SECOND NVARCHAR(20) = 'stringAfter'
DECLARE #SEARCHING NVARCHAR (20)
SET #SEARCHING = (SELECT SUBSTRING(#STRING, CHARINDEX(#FIRST, #STRING) + LEN(#FIRST), CHARINDEX(#SECOND, #STRING) - CHARINDEX(#FIRST, #STRING) - LEN(#FIRST)))
-- if you want to remove empty spaces
SET #SEARCHING = REPLACE(#SEARCHING, ' ', '')
SELECT #SEARCHING
Then output as below:
(No column name)
Searching

stripping strings between a comma in sql server

I know to do parts of it but not all of it, lets say my table name is REV and column name is DESCR and it has a value like
R&B , Semiprivate 2 Beds , Medical/Surgical/GYN
i use
SELECT DESCR, LEFT(DESCR, Charindex(',', DESCR)), SUBSTRING(DESCR, CHARINDEX(',', DESCR) + 1, LEN(DESCR)) from REV
i get 'R&B ,' in one column and 'Semiprivate 2 Beds , Medical/Surgical/GYN' in another column in the above select statement but i dont know how to selesct the strings from teh second comma onwards
what i like to return is 'R&B' in one column without the comma and 'Semiprivate 2 Beds' in another column and 'Medical/Surgical/GYN' so on
basically select test between commas and when there is no comma it should be blank
This should work:
SELECT
LEFT(DESCR, CHARINDEX(',', DESCR)-1),
SUBSTRING(DESCR, CHARINDEX(',', DESCR)+1, CHARINDEX(',', DESCR, CHARINDEX(',', DESCR)+1) - CHARINDEX(',', DESCR) -1 ),
RIGHT(DESCR, CHARINDEX(',', REVERSE(DESCR))-1)
FROM REV
This should work:
SELECT
LEFT(DESCR, CHARINDEX(',', DESCR)-1),
SUBSTRING(DESCR, CHARINDEX(',', DESCR)+1, LEN(DESCR)-CHARINDEX(',', DESCR)-CHARINDEX(',',REVERSE(DESCR ))),
RIGHT(DESCR, CHARINDEX(',', REVERSE(DESCR))-1)
FROM REV
Sample SQL Fiddle
This will split the string, but leave blank at the beginning and end of the strings, you can use LTRIMand RTRIMto trim away the blanks.
There might be better ways to do this though; see the article Split strings the right way – or the next best way by Aaron Bertrand at (that Andrew mentioned in a comment).

Parsing through a column to flip names using patindex

So I have a database of customers. I run SELECT * FROM MyTable it gives me back several columns, one of which is the name. Looks like this:
"Doe, John"
"Jones, Bill"
"Smith, Mike"
"Johnson, Bob"
"Harry Smith"
"Black, Linda"
"White, Laura"
etc. Some are last name, first name. Others are first name last name.
My boss wants me to flip the names so they are all first then last.
So I ran this:
SELECT SUBSTRING(Column_Name, CHARINDEX(',', Column_Name) + 2, LEN(Name) - CHARINDEX(',', Column_Name) + 1) + ' ' + SUBSTRING(Column_Name, 1, CHARINDEX(',', Column_Name) - 1) FROM MyTable
The problem is that when I run that, it only runs the names until it finds one it doesn't need to flip. So in the example above, it would only give me the first four names, not all of them.
It was suggested to me that I could use the PATINDEX() to pull out all of the names. I don't know how to use this and was hoping I could get some help with it.
I suspect your code has TRY/CATCH or you are otherwise swallowing/suppressing/ignoring errors. You should get 4 rows back and then a big ugly error message:
Msg 537, Level 16, State 2
Invalid length parameter passed to the LEFT or SUBSTRING function.
The problem is that your expression assumes that , always exists. You need to cater for that either by filtering out the rows that don't contain a , (though this is not very dependable, since the expression could be attempted before the filter), or the following way, where you make different decisions about how to reassemble the string based on whether a , is found or not:
DECLARE #x TABLE(y VARCHAR(255));
INSERT #x VALUES
('Doe, John'),
('Jones, Bill'),
('Smith, Mike'),
('Johnson, Bob'),
('Harry Smith'),
('Black, Linda'),
('White, Laura');
SELECT LTRIM(SUBSTRING(y, COALESCE(NULLIF(CHARINDEX(',',y)+2,2),1),255))
+ RTRIM(' ' + LEFT(y, COALESCE(NULLIF(CHARINDEX(',' ,y)-1,-1),0)))
FROM #x;
Results:
John Doe
Bill Jones
Mike Smith
Bob Johnson
Harry Smith
Linda Black
Laura White
You don't need PATINDEX in this case, although it could be used. I'd take your expression to flip the names and put it in a CASE expression.
DECLARE #MyTable TABLE
(
Name VARCHAR(64) NOT NULL
);
INSERT #MyTable(Name)
VALUES
('Doe, John'),
('Jones, Bill'),
('Smith, Mike'),
('Johnson, Bob'),
('Harry Smith'),
('Black, Linda'),
('White, Laura');
SELECT
CASE
WHEN CHARINDEX(',', Name, 1) = 0 THEN Name
ELSE SUBSTRING(Name, CHARINDEX(',', Name) + 2, LEN(Name) - CHARINDEX(',', Name) + 1)
+ ' ' + SUBSTRING(Name, 1, CHARINDEX(',', Name) - 1)
END AS [Name]
FROM #MyTable;
The first condition simply returns the original value if no comma was used.

Resources