Substring only if string length > 2 - sql

I was wondering if it was possible to only substring if the string length is > 2?
Here is my sample statement:
Select SUBSTRING(ABRESC, 1, 2) + '-' + SUBSTRING(ABRESC, 3, 5) AS ABRESC From TABLE
However, some fields are only 2 chars long so i was wondering if its possible to only substring when its longer than 2 chars?

You could use CASE
Select ABRESC =
CASE WHEN LEN(ABRESC) > 2
THEN SUBSTRING(ABRESC, 1, 2) + '-' + SUBSTRING(ABRESC, 3, 5)
ELSE ABRESC END
From TABLE

Related

SQL Server - Extract text from a given string field

What is the best method to extract the text from the string field below?
I am trying to extract the ProjectID numbers (91, 108, 250) below but am struggling because the ProjectIDs are either 2 or 3 integers long and are within different parts of the string.
Row Parameter
1 ProjectID=91&GroupID=250&ParentID=1
2 ProjectID=108&GroupID=250&ParentID=35
3 GroupID=1080&ProjectID=250&ParentID=43
4 ProjectID=250
Any help would be much appreciated.
SQL Server is kind of lousy on string functionality. Here is one method:
select left(v1.p, patindex('%[^0-9]%', v1.p + ' ') - 1)
from (values ('ProjectID=91&GroupID=250&ParentID=1'),
('ProjectID=108&GroupID=250&ParentID=35'),
('GroupID=1080&ProjectID=250&ParentID=43'),
('ProjectID=250')
) v(parameter) cross apply
(values (stuff(v.parameter, 1, charindex('ProjectID=', v.parameter) + 9, ''))
) v1(p);
Or split the string and look for a match:
select stuff(s.value, 1, 10, '')
from (values ('ProjectID=91&GroupID=250&ParentID=1'),
('ProjectID=108&GroupID=250&ParentID=35'),
('GroupID=1080&ProjectID=250&ParentID=43'),
('ProjectID=250')
) t(parameter) cross apply
string_split(t.parameter, '&') s
where s.value like 'ProjectId=%';
Here is a db<>fiddle.
SELECT
substring ( #Parameter,
CHARINDEX('ProjectID', #Parameter) + 10,
CHARINDEX('&', #parameter, CHARINDEX('ProjectID', #Parameter)) -
(CHARINDEX('ProjectID', #Parameter) + 10))
from table

how to replace a value for string if letters are missing?

I ran into a problem where i have to create a 'LettersOfName' column. As name suggest I have to get letter 2,3 and 5 from ORGANISATIONNAME column and letters 2 and 3 from CLIENTLASTNAME column, then concatenate to form letters of name column. The condition is if letters of name is not equal to length 5 than replace with '22222' also if any of the letters is missing from first name and last name than replace with '22222'. I am using this query.
select
( CASE WHEN LENGTH (UPPER( SUBSTR(ORGANISATIONNAME, 2,2) || SUBSTR(ORGANISATIONNAME,5,1)) || UPPER(SUBSTR(CLIENTLASTNAME,2,2))) != '5' THEN '22222'
ELSE UPPER( SUBSTR(ORGANISATIONNAME, 2,2) || SUBSTR(ORGANISATIONNAME,5,1)) || UPPER(SUBSTR(CLIENTLASTNAME,2,2)) END)
AS LETTERSOFNAME
from client;
So, far this query runs fine, but when we have name like 'Jo Anne' or 'J Shark' it is missing letter '2' and '3' but does not replace the string with '22222'. When length is not equal to 5 it replaces with '22222'. I am using Oracle 12c.
If after the concatenations of the letters you remove all the spaces and the length of the remaining string is less than 5 then replace with '22222':
SELECT
CASE
WHEN LENGTH(REPLACE(SUBSTR(ORGANISATIONNAME, 2, 2) || SUBSTR(ORGANISATIONNAME, 5, 1) || SUBSTR(CLIENTLASTNAME, 2, 2), ' ', '')) < 5 THEN '22222'
ELSE UPPER(SUBSTR(ORGANISATIONNAME, 2, 2) || SUBSTR(ORGANISATIONNAME, 5, 1) || SUBSTR(CLIENTLASTNAME, 2, 2))
END LETTERSOFNAME
FROM client
Or with a CTE:
WITH cte AS (
SELECT
UPPER(REPLACE(
SUBSTR(ORGANISATIONNAME, 2, 2) ||
SUBSTR(ORGANISATIONNAME, 5, 1) ||
SUBSTR(CLIENTLASTNAME, 2, 2),
' ',
''
)) LETTERSOFNAME
FROM client
)
SELECT
CASE
WHEN LENGTH(LETTERSOFNAME) < 5 THEN '22222'
ELSE LETTERSOFNAME
END LETTERSOFNAME
FROM cte
See the demo.
You should first remove the white space between the string and and then apply your case statement on it
replace ('J Shark', ' ', '')
Reason is white space is being counted as a character in J Shark and that is why second and third characters are missing.
Here is an example demo.
Here is my approach:
Put both columns ORGANISATIONNAME and CLIENTLASTNAME to another table with identity column (to identify each row)
Write a function to split text by a string (in this case pass a space)
Get the identity and the splitted data to 2 tables each for column 1 and 2
Consider each table and apply your logic
Concatenate the row values separated by space, with the ID (1 record per ID)
Join the 2 tables (by IDs)
Join the 2 tables for matches in Col-Split data, and get the IDs
Now Query for the data in table in above 1

Get first n characters from a string write them and continue to get the next n characters and write them

I am trying to deal with some random numbers from a list.
What I am trying to achieve is to paste the numbers on multiple columns of max 35 char per column.
If there is a comma after, let's say char 32 and the next number has 6 char, I want to have the 32 char in column 1 and the next 35 chars from char 32 to in column 2, same condition, if there is a comma I would paste less.
I've only tried the cases until now, and I could get the 1st column, but I can't move to the next one.
declare #string varchar(max)
set #string= '2344,2343,5645465,546456,43645645,654656,5765765,6576467,7576576,35345435'
select
CASE WHEN (LEN(REPLACE(#string, ',', ';')) >= 35 ) THEN REVERSE(SUBSTRING(REVERSE(LEFT(REPLACE(#string, ',', ';'), 35)), CHARINDEX(';', REVERSE(LEFT(REPLACE(#string, ',', ';'), 35)))+1, 35)) ELSE REPLACE(#string, ',', ';') END as fact1,
'' as fact2,
'' as fact3,
'' as fact4
From string '2344,2343,5645465,546456,43645645,654656,5765765,6576467,7576576,35345435'
I would like:
column 1: 2344,2343,5645465,546456,43645645
column 2: 654656,5765765,6576467,7576576
column 3: 35345435
column 4:
Assuming SQL Server here, you could use a recursive CTE to first get the parts of the strings distributed on rows.
You need to split the string into a left and a right part. To get the proper position where to split take the whole 35 characters on the left, reverse it and look for the first comma in that reverse. That gives you the difference you need to correct the 35 with.
You can also have a running number in the CTE. So you can pick any number in a subquery in a SELECT without a FROM to get such a row as a column.
DECLARE #string varchar(max);
SET #string = '2344,2343,5645465,546456,43645645,654656,5765765,6576467,7576576,35345435';
WITH
cte
AS
(
SELECT 1 n,
left(#string, 35 - charindex(',', reverse(left(#string, 35)))) l,
CASE
WHEN len(#string) - 35 + charindex(',', reverse(left(#string, 35))) - 1 >= 0 THEN
right(#string, len(#string) - 35 + charindex(',', reverse(left(#string, 35))) - 1)
ELSE
''
END r
UNION ALL
SELECT n + 1 n,
left(r, 35 - charindex(',', reverse(left(r, 35)))) l,
CASE
WHEN len(r) - 35 + charindex(',', reverse(left(r, 35))) - 1 >= 0 THEN
right(r, len(r) - 35 + charindex(',', reverse(left(r, 35))) - 1)
ELSE
''
END r
FROM cte
WHERE len(r) > 0
)
SELECT (SELECT l
FROM cte
WHERE n = 1) [column 1],
(SELECT l
FROM cte
WHERE n = 2) [column 2],
(SELECT l
FROM cte
WHERE n = 3) [column 3],
(SELECT l
FROM cte
WHERE n = 4) [column 4];
db<>fiddle

Replace first or last character is * with % SQL server

I have string:
*rg*niza*io*
I want to replace % in the first and last character of the string. Desired out put is:
%rg*niza*io%
I'm just answering because the obvious to me is:
select '%' + substring(str, 2, len(str) - 2) + '%'
Of course, this would be a bit more complicated if you want to conditionally replace the characters when they are '*'.
If you want to replace only * with % from first and last positions. Then,
Query
SELECT CASE
WHEN LEFT([string_column], 1) = '*' AND RIGHT([string_column], 1) = '*'
THEN '%' + SUBSTRING([string_column], 2, LEN([string_column]) - 2) + '%'
WHEN LEFT([string_column], 1) = '*' AND RIGHT([string_column], 1) <> '*'
THEN '%' + RIGHT([string_column], LEN([string_column]) - 1)
WHEN LEFT([string_column], 1) <> '*' AND RIGHT([string_column], 1) = '*'
THEN LEFT([string_column], LEN([string_column]) - 1) + '%'
ELSE [string_column] END AS [updated_string_column]
FROM [your_table_name];
Demo
Use STUFF,LEFT and LEN string functions
Declare #string varchar(50) = '*rg*niza*io*'
select stuff(left(#string,len(#string)-1),1,1,'%')+'%'
Result : %rg*niza*io%
Use a combination of the CONCAT, LEFT, SUBSTRING & LEFT functions.
SELECT CONCAT('%',LEFT(SUBSTRING(yourfield,2,LEN(yourfield)),LEN(yourfield)-2),'%')
FROM yourtable
Output: %rg*niza*io%

Convert varchar to 3 (sometimes 4) chars in T-SQL

I select data from a database. The values are (field name is ADR_KOMP_VL) :
4 , 61A, 100, 12, 58, 123C, 6 A, 5
I need to convert these values to 3 digits (except when there is a letter then it is 4)
So the converted values should be:
004, 061A, 100, 012, 058, 123C, 006A, 005
The rules are:
Always 3 digits
No spaces
If the original value is less than three digits, put 0's in front of it.(The length is 3)
If the original value contains a letter, put 0's in front of it (but the length is 4)
For the "no space" part I have this:
select REPLACE(ADR_KOMP_VL, ' ','')
The solution I have so far is:
SELECT RIGHT('000' + CONVERT(VARCHAR(4),REPLACE(ADR_KOMP_VL, ' ','')), 3)
But this only gives me the right length, when there is no letter in the value. My problem is how to handle the values with a letter in them??
This only check if the last character is letter. Additional logic will be required if that's not the case
SELECT REPLICATE('0', CASE WHEN ISNUMERIC(RIGHT(ADR_KOMP_VL, 1)) = 0 THEN 4
ELSE 3
END - LEN(REPLACE(ADR_KOMP_VL, ' ', '')))
+ REPLACE(ADR_KOMP_VL, ' ', '')
FROM TX
EDIT - actually this might work better, checks for whole ADR_KOMP_VL if it's numeric:
SELECT REPLICATE('0', CASE WHEN ISNUMERIC(REPLACE(ADR_KOMP_VL, ' ', '')) = 0 THEN 4
ELSE 3
END - LEN(REPLACE(ADR_KOMP_VL, ' ', '')))
+ REPLACE(ADR_KOMP_VL, ' ', '')
FROM TX
SQLFiddle DEMO
You can use a case statement:
SELECT (case when ADR_KOMP_VL like '%[A-Z]%'
then RIGHT('0000' + CONVERT(VARCHAR(4),REPLACE(ADR_KOMP_VL, ' ','')), 4)
else RIGHT('000' + CONVERT(VARCHAR(4),REPLACE(ADR_KOMP_VL, ' ','')), 3)
end)