Max of a part of split string - sql

I have, in my DB oracle 10g, a field that contains references.
It's stored as : name/yyyy/mm/number
The new number, is the max number found in the part mm/number.
So, for now, I have a split of my string that gives me a list of str_array like this :
str_array(name, yyyy, mm, number)
I'd like, with this, found max number, for the couple mm/number.
Is this possible to do this?
Can I have something like :
SELECT MAX(split(reference, '/').lastPartOfArray) into nb
FROM table
where lastPartOfArray-1 = sysdate.month;
Data samples :
Smith/2013/12/1
Smith/2013/11/1
Smith/2013/12/3
Jones/2013/12/6
Smith/2013/12/3
Jones/2013/11/7
Since we are in the month 12, a max on those data must give me 6 into nb.
The number part, has no limit, it can be 1000, 10000...
The part Jones/2013 doesn't really matter for the number. But I can't have the same number, for a month.
My apologies, I don't know if this is possible, so I tried to write what I want in the query.
Is this possible, or should I create more than one field in my table(name/yyyy, mm, number)?
edit : valex answer and some custom
select MAX(CAST(SUBSTR(num,INSTR(num,'/')+9,1000) as Int))
from T
where num like TO_CHAR(sysdate,'%/YYYY/MM/%')
So this, count searching first occurence.
select MAX(CAST(SUBSTR(num,INSTR(num,'/',1 ,n)+1,1000) as Int))
from T
where num like TO_CHAR(sysdate,'%/YYYY/MM/%')
This found the n occurence of the char.
This is a helpful solution in other cases.

To get a maximum you should convert this last part into INT values otherwise you can get not right results because of STRING comparing rules will be used.
As soon as /YYYY/MM/ has got a fixed length = 9 so we can find first \ position and add 9 to this position to find a last part number substring start.
Here is an example:
select MAX(CAST(SUBSTR(num,INSTR(num,'/')+9,1000) as Int))
from T
where num like TO_CHAR(sysdate,'%/YYYY/MM/%')
SQLFiddle demo
Also you can exclude wrong formatted values from this query to avoid conversion errors using the following way:
select MAX(CAST(SUBSTR(num,INSTR(num,'/')+9,1000) as Int))
from T
where num like TO_CHAR(sysdate,'%/YYYY/MM/%')
AND
LENGTH(TRIM(TRANSLATE(SUBSTR(num,INSTR(num,'/')+9,1000),
' 0123456789', ' '))) is null
SQLfiddle demo

Try this:
SELECT
MAX(SUBSTR(num, INSTR(num, '/', 1, 3) + 1))
FROM ref
WHERE
SUBSTR(num, INSTR(num, '/', 1, 2) + 1, INSTR(num, '/', 1, 3) - INSTR(num, '/', 1, 2) - 1) = TO_CHAR(sysdate, 'MM')
Sample: http://sqlfiddle.com/#!4/1b03a/1

Related

Date is not displaying correct with substr & like query

I am trying to get this out out,
but i am experiencing that the substr i am using is incorrect ,
For an example , all my columns are displaying
hdfs://asdasda/asdas/fdsfdsfd/received_files/asdasd_20191231_11122333_123456789_CO.dat
some of which has more character so in order for me to get the exact date in the column is inconsistent if i am using subsring
some will return 20191230
but some will return _2020123
How do we tackle this problem ?
i am trying to display only data , this is using sql language or hue ,
when i input my script in ,
select SUBSTR(input_file_name, LENGTH(input_file_name) - 44, 9) from th_ingestion_status limit 100
i feel my script for Like and substr statement is incorrect
I you want the first sequence of 8 digits surrounded by underscores, use regexp_extract():
select regexp_extract(filename, '_([0-9]{8})_', 1)
If you need this after the last /, then:
select regexp_extract(filename, '_([0-9]{8})_[^/]*$', 1)
Please use below query, also please mention the database you are using, so that can provide relevant query
substr(column_name, instr(column_name, '_', 1, 2) +1, 6)
Oracle Test Case:
select 'hdfs://asdasda/asdas/fdsfdsfd/received_files/asdasd_20191231_11122333_123456789_CO.dat', substr('hdfs://asdasda/asdas/fdsfdsfd/received_files/asdasd_20191231_11122333_123456789_CO.dat', instr('hdfs://asdasda/asdas/fdsfdsfd/received_files/asdasd_20191231_11122333_123456789_CO.dat', '_', 1, 2) +1, 6)
from dual;

SQL QUERY to bring last letter in a string to first letter position using SQL Server

I have a column called Supervisor from a table JobData in a SQL Server database. In this Supervisor column the records are of the format below.
DANNYL
ADITYAG
SAMMYS
BOBBYJ
I want to convert these records to lower case and bring the last letter to first letter. For example, DANNYL should be changed to the format ldanny and this format should be applied to all the remaining records.
Can anyone help me out with a SQL query for this?
You can use the following solution using LEFT and RIGHT to get the parts of the name. By using LOWER you can convert the upper case characters to lower case:
SELECT LOWER(RIGHT(Supervisor, 1) + LEFT(Supervisor, LEN(Supervisor) - 1))
FROM JobData
WHERE LTRIM(RTRIM(Supervisor)) <> ''
-- or using ABS on the length - 1 so the WHERE isn't needed.
SELECT LOWER(RIGHT(Supervisor, 1) + LEFT(Supervisor, ABS(LEN(Supervisor) - 1)))
FROM JobData
Since it looks like the column Supervisor contains empty values you can also use the following solution without calculation and not failing on the empty values:
SELECT LOWER(RIGHT(Supervisor, 1) + REVERSE(SUBSTRING(REVERSE(Supervisor), 2, LEN(Supervisor))))
FROM JobData
... and another possibility using STUFF:
SELECT LOWER(LEFT(STUFF(Supervisor, 1, 0, RIGHT(Supervisor, 1)), LEN(Supervisor)))
FROM JobData
demo on dbfiddle.uk
there is probably a better way do to that , but here is my proposition.
SELECT lower(left(right('DANYL',1)+'DANYL',len('DANYL')))
Using SUBSTRING you can get the expected result:
SELECT LOWER(CONCAT(SUBSTRING(Supervisor, LEN(Supervisor), 1), SUBSTRING(Supervisor, 0, LEN(Supervisor))))
FROM JobData
Demo with the given sample data:
DECLARE #JobData TABLE (Supervisor VARCHAR(100));
INSERT INTO #JobData (Supervisor) VALUES
('DANNYL'), ('ADITYAG'), ('SAMMYS'), ('BOBBYJ');
SELECT LOWER(CONCAT(SUBSTRING(Supervisor, LEN(Supervisor), 1), SUBSTRING(Supervisor, 0, LEN(Supervisor)))) AS Supervisor
FROM #JobData
Output:
ldanny
gaditya
ssammy
jbobby
Like this? :
SELECT
LOWER(CONCAT(SUBSTRING([Supervisor], LEN([Supervisor]), 1),SUBSTRING([Supervisor], 1, ABS(LEN([Supervisor])-1))))
FROM TABLE

How can I extract part of a string with different lengths and insert it into a table?

I uploaded some data from excel sheet to a table in sql , I would like to use part of the string that I inserted into the column PPRName and insert into another table [Verify].
The data in the column when inserted looks like this:
August 2018 [ NW: Construction MTP021 - Building and Civil Construction: Masonry NQF 3 ]
I want to insert this part of the string :
NW: Construction MTP021 - Building and Civil Construction: Masonry NQF 3
into another table [Verify] for every PPR Name in the PPRName column. The names of the PPRs vary in length but all come in same format.
I would also like to extract the August 2018 and cast it as a date and insert into my table [Verify].
I am not sure how to use Charindex and Substrings to achieve this.
i tried this but no data was returned
select SUBSTRING([PPR_Caption],charindex('[',[PPR_Caption]),charindex([PPR_Caption],']'))
FROM [dbo].[PPRS]
You incorrectly use the 2nd CHARINDEX and you incorrectly use the SUBSTRING commands.
SELECT SUBSTRING(PPR_Caption, CHARINDEX("[", PPR_Caption) + 1, CHARINDEX("]", PPR_Caption) - CHARINDEX("[", PPR_Caption) - 1)
FROM PPRS
SUBSTRING uses a start and a lenght, not the start and end point. To get the length use your end point and substract the start point (and correct the 1 position offset with -1).
In your 2nd CHARINDEX you switched the string to search in and the string to look for.
String operations like this are cumbersome in SQL Server.
Try this:
select replace(v2.str_rest, ' ]', '') as name, cast(str_start as date) as dte
from (values ('August 2018 [ NW: Construction MTP021 - Building and Civil Construction: Masonry NQF 3 ]')
) v(str) cross apply
(values (stuff(v.str, 1, charindex('[', str) + 1, ''), substring(v.str, 1, charindex('[', str) -1))
) v2(str_rest, str_start);
SQL Server is pretty good about guessing formats for converting dates, so it will actually convert the date without the day of the month.

ORA-01722: invalid number - value with two decimals

I'm trying to get the max value from a text field. All but two of the values are numbers with a single decimal. However, two of the values have something like 8.2.10. How can I pull back just the integer value? The values can go higher than 9.n, so I need to convert this field into a number so that I can get the largest value returned. So all I want to get back is the 8 from the 8.2.1.
Select cast(VERSION as int) is bombing out because of those two values with a second . in them.
You may derive by using regexp_substr with \d pattern :
with tab as
(
select regexp_substr('8.2.1', '\d', 1, 1) from dual
union all
select regexp_substr('9.0.1', '\d', 1, 1) from dual
)
select * from tab;
For Oracle you must attend the value as string for retire only the part before the dot. Ex:
SELECT NVL( SUBSTR('8.2.1',0, INSTR('8.2.1','.')-1),'8.2.1') AS SR FROM DUAL;
Check than the value is repeated 3 times in the sentence, and if the value is zero or the value didn't have decimal part then it will return the value as was set.
I had to use T-SQL rather PL/SQL, but the idea is the same:
DECLARE #s VARCHAR(10);
SELECT #s='8.2.1';
SELECT CAST(LEFT(#s, CHARINDEX('.', #s) - 1) AS INT);
returns the integer 8 - note that it won't work if there are no dots because it takes the part of the string to the left of the first dot.
If my quick look at equivalent functions was correct, then in Oracle that would end up as:
SELECT CAST(SUBSTR(VERSION, 1, INSTR(VERSION, '.') - 1) AS INT)

SQL Plus show first four and last 4 numbers in the output

How can I select a columns first 4 digits and last 4 digits and use an "X" placement for all the numbers in between?
Example
SELECT id from users where user_name ='Tom';
Output
5958694850384567
I am trying to get only the first and last 4 numbers with x's as placements to any number that is being masked:
Trying to get it to look like
Output:5958XXXXXXXX4567
Here is my query so far:
SELECT SUBSTR(id, 1, 4) from users
where user_name ='Tom'
Thank you for your time!
Have you considered simply use the LEFT() and RIGHT() functions? These will give you a specific number of characters from the left or right of a given string respectively.
You can also combine those to build your complete string using the CONCAT() function:
SELECT CONCAT(LEFT(id, 4), 'XXXXXXXX', RIGHT(id, 4))
FROM users
WHERE user_name = 'Tom'
Additionally, if you don't always have a given number of characters within the string, you could calculate the middle section of your output as well via the REPLICATE() function and a bit of math:
SELECT CONCAT(LEFT(id, 4), REPLICATE('X', LEN(id) - 8), RIGHT(id, 4))
FROM users
WHERE user_name = 'Tom'
Oracle Version
I didn't realize that you were using Oracle specifically and assumed SQL Server, so I'll provide some similar code to handle this in that flavor:
SELECT LEFT(id, 4) || RPAD('X', LEN(id) - 8, 'X') || RIGHT(id, 4)
FROM users
WHERE user_name = 'Tom'