SQL - Pulling everything after last forward slash - spotfire

I'm trying to pull the string to the right of the last forward slash in the string below.
/Applied Analytics/URMFG/Service Analysis/ServiceAnalysis
So basically, I would like to see ServiceAnalysis returned.
I've come across the following SQL, which is close to what I need, but it's not exact.
=MID(K19, FIND("/",K19)+1, LEN(K19))

DECLARE #test NVARCHAR(100)
SET #test = '/Applied Analytics/URMFG/Service Analysis/ServiceAnalysis'
SELECT REVERSE(LEFT(REVERSE(#test), CHARINDEX('/', REVERSE(#test)) -1))
Reverse the String and find first instance of /
Find characters to the left of /
Reverse again to get your desired result

In SQL, you could do this:
declare #string varchar(100) = '/Applied Analytics/URMFG/Service Analysis/ServiceAnalysis';
select RIGHT(#string,charindex('/',reverse(#string),1)-1)
However, still waiting to see if it's EXCEL you're referencing (since that looks like an EXCEL formula).
If it is Excel, then you can use the Reverse() function from this post and apply it like this:
Here's the formula:
=Reverse(LEFT(Reverse(A1),FIND("/",Reverse(A1),1)-1))

Regular Expressions to the rescue! you can achieve this using the RXReplace() function:
RXReplace([column],"^/.*/(.*)$","$1","")
I'll let you look up the RXReplace() documentation on your own, but just to explain the regex itself:
^/ matches the beginning of the string and the starting /
.*/ matches any characters that come next, followed by a / which is the final / before the end of the string (and preceeding the bit that we want to extract)
(.*)$ matches any characters that come next, putting them into a "capturing group" (basically a variable), followed by the end of the string
the $1 is a token which refers to the capturing group above (normally this looks like \1 in regex, but Spotfire is a bit different)
pretty much any time you need to deal with extracting bits of strings in Spotfire expressions, RXReplace() is what you want. it's a lot more sustainable than doing a ton of Left()s, Right()s, and Len()s, although the initial effort can be a bit higher.
more regex info at http://www.regular-expressions.info/.

Another additional approach using PARSENAME() function
DECLARE #String NVARCHAR(100)
SET #String = '/Applied Analytics/URMFG/Service Analysis/ServiceAnalysis'
SELECT PARSENAME(REPLACE(SUBSTRING(#String, 2, 100), '/', '.'), 1) AS [4th part],
PARSENAME(REPLACE(SUBSTRING(#String, 2, 100), '/', '.'), 2) AS [3rd part],
PARSENAME(REPLACE(SUBSTRING(#String, 2, 100), '/', '.'), 3) AS [2nd part],
PARSENAME(REPLACE(SUBSTRING(#String, 2, 100), '/', '.'), 4) AS [1st part]
output

The following SQL Statement worked for me in T-SQL 2017:
SELECT RIGHT([Filename], CHARINDEX('\', REVERSE('\' + [Filename])) - 1)

Related

Replacing a certain part of string with a pre-specified Value

I am fairly new to Puppet and Ruby. Most likely this question has been asked before but I am not able to find any relevant information.
In my puppet code I will have a string variable retrieved from the fact hostname.
$n="$facts['hostname'].ex-ample.com"
I am expecting to get the values like these
DEV-123456-02B.ex-ample.com,
SCC-123456-02A.ex-ample.com,
DEV-123456-03B.ex-ample.com,
SCC-999999-04A.ex-ample.com
I want to perform the following action. Change the string to lowercase and then replace the
-02, -03 or -04 to -01.
So my output would be like
dev-123456-01b.ex-ample.com,
scc-123456-01a.ex-ample.com,
dev-123456-01b.ex-ample.com,
scc-999999-01a.ex-ample.com
I figured I would need to use .downcase on $n to make everything lowercase. But I am not sure how to replace the digits. I was thinking of .gsub or split but not sure how. I would prefer to make this happen in a oneline code.
If you really want a one-liner, you could run this against each string:
str
.downcase
.split('-')
.map
.with_index { |substr, i| i == 2 ? substr.gsub(/0[0-9]/, '01') : substr }
.join('-')
Without knowing what format your input list is taking, I'm not sure how to advise on how to iterate through it, but maybe you have that covered already. Hope it helps.
Note that Puppet and Ruby are entirely different languages and the other answers are for Ruby and won't work in Puppet.
What you need is:
$h = downcase(regsubst($facts['hostname'], '..(.)$', '01\1'))
$n = "${h}.ex-ample.com"
notice($n)
Note:
The downcase and regsubst functions come from stdlib.
I do a regex search and replace using the regsubst function and replace ..(.)$ - 2 characters followed by another one that I capture at the end of the string and replace that with 01 and the captured string.
All of that is then downcased.
If the -01--04 part is always on the same string index you could use that to replace the content.
original = 'DEV-123456-02B.ex-ample.com'
# 11 -^
string = original.downcase # creates a new downcased string
string[11, 2] = '01' # replace from index 11, 2 characters
string #=> "dev-123456-01b.ex-ample.com"

How do I delete text before the last forward slash in a column?

I have a spreadsheet with columns that show a filepath. They look like this:
/j/t/jtfdsrn-01r_1_1_19.jpg
/j/t/jtfdsrn-01r_1_1_18.jpg
/j/t/jtfdsrn-01r_1_1_17.jpg
/j/t/jtfdsrn-01r_1_1_16.jpg
/j/t/jtfdsrn-01r_1_1_15.jpg
/j/t/jtfdsrn-01r_1_1_14.jpg
/j/t/jtfdsrn-01r_1_1_13.jpg
/j/t/jtfdsrn-01r_1_1_12.jpg
I want to remove everything before the last slash so they look like this:
/jtfdsrn-01r_1_1_19.jpg
/jtfdsrn-01r_1_1_18.jpg
/jtfdsrn-01r_1_1_17.jpg
/jtfdsrn-01r_1_1_16.jpg
/jtfdsrn-01r_1_1_15.jpg
/jtfdsrn-01r_1_1_14.jpg
/jtfdsrn-01r_1_1_13.jpg
/jtfdsrn-01r_1_1_12.jpg
Can I do this with a formula or an built-in function? I use OpenOffice.
I have tried the TRIM(RIGHT(SUBSTITUTE(A1,"/",REPT(" ",LEN(A1))),LEN(A1))) formula but I get a Error:501 on it.
If your target string is always the same length:
=RIGHT(A1,23)
Input: /j/t/jtfdsrn-01r_1_1_19.jpg Output: /jtfdsrn-01r_1_1_19.jpg
If you have variable length strings and always 3 backslashes in filepath:
="/" &RIGHT(A1, LEN(A1) -FIND("*", SUBSTITUTE(A1,"/","*",3), 1))
Input: /j/t/jtfdsrn-01r_1_1_1000.jpg Output: /jtfdsrn-01r_1_1_1000.jpg
If you have variable length strings and variable backslashes in filepath:
="/" &RIGHT(A1, LEN(A1) -FIND("*", SUBSTITUTE(A1,"/","*", LEN(A1)-LEN(SUBSTITUTE(A1,"/","") )), 1))
Input: a/b/c/j/t/jtfdsrn-01r_1_1_19.jpg Output: /jtfdsrn-01r_1_1_19.jpg
Let me know if this works for you if your values dont change there shouldnt be an issue but if so ill look into it.
=RIGHT(A2;LEN(A2)-FIND("/";A2;3)-1)
Simply Use Wildcard (*/) Without Brackets In Find and Replace

Getting a string value that is between two characters

I need to get the value that is between !03 and !03.
Example:
JDC!0320151104!03OUT
I should get following string in return: 20151104
NOTE: The string isn't always 22 characters long, but I am only concerned with the value that is between !03 and !03.
This is what I have so far. I couldn't make any progress further than this:
SELECT
SUBSTRING(
RegStatsID,
CHARINDEX('!', RegStatsID) + 3,
CHARINDEX('!', REVERSE(RegStatsID))
)
From TableX
Great that you found a solution!
This might be better:
By replacing the "!03" with XML-tags you can easily pick the second "node". Your string will be transformed into <x>JDC</x><x>20151104</x><x>OUT</x>:
DECLARE #test VARCHAR(100)='JDC!0320151104!03OUT';
SELECT CAST('<x>' + REPLACE(#test,'!03','</x><x>') + '</x>' AS XML).value('/x[2]','datetime')
One advantage was to get the value between the two "!03" typed. In this case you get a "real" datetime back without any further casts. If the value there is not a datetime (or date) in all cases, you just use nvarchar(max) as type.
Another advantage was: If you - why ever - need the other values later, you just have them with .value('/x[1 or 3]'...)
I was able to get it right by doing following:
SELECT
SUBSTRING(
RegStatsID,
CHARINDEX('!', RegStatsID) + 3,
len(RegStatsID) - CHARINDEX('!', RegStatsID ) - 2 - CHARINDEX('!', Reverse(RegStatsID))
)

Using REGEXP_SUBSTR to get key-value pair data

I have a column with below values,
User_Id=446^User_Input=L307-60#/25" AP^^
I am trying to get each individual value based on a specified key.
All value after User_Id= until it encounters ^
All value after User_Input= until it encounters ^
I tried for and so far I have this,
SELECT LTRIM(REGEXP_SUBSTR('User_Id=446^User_Input=L307-60#/25" AP^'
,'[0-9]+',1,1),'^') User_Id
from dual
How do I get the value for the User_Input??
P.S: User input can have anything, like ',", *,% including a ^ in the middle of the string (that is, not as a delimiter).
Any help would be greatly appreciated..
This can be easily solved using boring old INSTR to calculate the offsets of the start and end points for the KEY and VALUE strings.
The trick is to use the optional occurrence parameter to identify each the correct instance of =. Because the input can contain carets which aren't intended as delimiters we need to use a negative position to identify the last ^.
with cte as (
select kv
, instr(kv, '=', 1, 1)+1 as k_st -- first occurrence
, instr(kv, '^', 1) as k_end
, instr(kv, '=', 1, 2)+1 as v_st -- second occurrence
, instr(kv, '^', -1) as v_end -- counting from back
from t23
)
select substr(kv, k_st, k_end - k_st) as user_id
, substr(kv, v_st, v_end - v_st) as user_input
from cte
/
Here is the requisite SQL Fiddle to prove it works. I think it's much easier to understand than any regex equivalent.
If there is no particular need to use Regex, something like this returns the value.
WITH rslt AS (
SELECT 'User_Id=446^User_Input=L307-60#/25" AP^' val
FROM dual
)
SELECT LTRIM(SUBSTR(val
,INSTR(val, '=', 1, 2) + 1
,INSTR(val, '^', 1, 2) - (INSTR(val, '=', 1, 2) + 1)))
FROM rslt;
Of course, if you can't guarantee that there will not be any carets that are valid text characters, this will possibly return partial results.
Assuming that you will always have 'User_Id=' and 'User_Input=' in your string, I would use a character group approach to parsing
Use the starting anchor,^, and ending anchor, $. Look for 'User_Id=' and 'User_Input='
Associate the value you are searching for with a character group.
SCOTT#dev>
1 SELECT REGEXP_SUBSTR('User_Id=446^User_Input=L307-60#/25" AP^','^User_Id=(.*\^)User_Input=(.*\^)$',1, 1, NULL, 1) User_Id
2* FROM dual
SCOTT#dev> /
USER
====
446^
SCOTT#dev>
1 SELECT REGEXP_SUBSTR('User_Id=446^User_Input=L307-60#/25" AP^','^User_Id=(.*\^)User_Input=(.*\^)$',1, 1, NULL, 2) User_Input
2* FROM dual
SCOTT#dev> /
USER_INPUT
================
L307-60#/25" AP^
SCOTT#dev>
Got this answer from a friend of mine.. Looks simple and works great...
SELECT
regexp_replace('User_Id=446^User_Input=L307-60#/25" AP^^', '.*User_Id=([^\^]+).*', '\1') User_Id,
regexp_replace('User_Id=446^User_Input=L307-60#/25" AP^^', '.*User_Input=(.*)[\^]$', '\1') User_Input
FROM dual
Posting here just in case any of you find it interesting..

Oracle/SQL - Removing undefined chars from string

I currently have an assignemnt where i have to handle data from a lot of countries. My customer have given me a list of acceptable characters, lets call it:
'aber =*'
All other characters should just be changed to '_'.
I know the conversion for my country's specific chars (æøå), easily done with something like
select replace ('Ål', 'Å', 'AA') from dual;
But how would i go about removing all unwanted "noise" without splitting it up in char-by-char comparison?
For example "bear*2 = fear" should become "bear*_ = _ear" as 2 and f are not in the accepted list.
Oracle 10g and up. As one of the approaches, you can use regular expression function regexp_replace():
select regexp_replace('bear*2 = fear', '[^aber =*]', '_') as res
from dual
res
------------------------------
bear*_ = _ear
Find out more about regexp_replace() function.

Resources