How to pickup date from long string Name column in oracle - mysql

I have table with column 'ID', 'File_Name'
Table
ID File_Name
123 ROSE1234_LLDAtIInstance_03012014_04292014_190038.zip
456 ROSE1234_LLDAtIInstance_08012014_04292014_190038.zip
All I need is to pickup the first date given in file name.
Required:
ID Date
123 03012014
456 08012014

Here's one method assuming 8 characters after 2nd _ is always true.
It finds the position of the first _ then looks for the position of the 2nd _ using the position of the first _+1 then it looks for the 8 characters after the 2nd _
SELECT Id
, substr(File_name, instr(File_name,'_',instr(File_name,'_')+1)+1,8) as Date
FROM Table
or
a more elegant way would be to use a RegExp_Instr Function which eliminates the need for nesting instr.
SELECT Id, substr(File_name,REGEXP_INSTR(FileName,'_',1,2)+1,8) as date
FROM dual;

Why don't you simply put the date in separate column? E.g. you can than query the (indexed) date. The theory says the date is a property of the file. It's about avoiding errors, maintainability and so on. What in the zip files? Excel sheets I suppose :-)

Use a much simplified call to REGEXP_SUBSTR( ):
SQL> with tbl(ID, File_name) as (
2 select 123, 'ROSE1234_LLDAtIInstance_03012014_04292014_190038.zip' from dual
3 union
4 select 456, 'ROSE1234_LLDAtIInstance_08012014_04292014_190038.zip' from dual
5 )
6 select ID,
7 REGEXP_SUBSTR(File_name, '_(\d{8})_', 1, 1, NULL, 1) "Date"
8 from tbl;
ID Date
---------- ----------------------------------------------------
123 03012014
456 08012014
SQL>
For 11g, click here for the parameters to REGEXP_SUBSTR( ).
EDIT: Making this a virtual column would be another way to handle it. Thanks to Epicurist's post for the idea. The virtual column will contain a date value holding the filename date once the ID and filename are committed. Add it like this:
alter table X_TEST add (filedate date generated always as (TO_DATE(REGEXP_SUBSTR(Filename, '_(\d{8})_', 1, 1, NULL, 1), 'MMDDYYYY')) virtual);
So now just insert the ID and Filename, commit and there's your filedate. Note that its read-only.

Related

Compairing two strings in MYSQL

I have a sequence of 20 numbers from 0 to 2, I want to compare this string with other sequences saved in my database, the problem is that the lenght of the strings saved on the database fluctuates.Also the comparison needs to be done from the end to the start.
Example of what I want:
20 digits string:
'1,1,2,1,2,1,0,1,2,1,2,1,0,1,2,1,1,1,2,1'
couple of strings saved in the database:
1 - '1,1,2,1'
2 - '2,1,2,2,2,2'
3 - '2,1'
4 - '1,1,2,1,2,1'
In this case the query would return the 1 and 3 only
create table mytable ( s varchar(60) );
insert into mytable values
('1,1,2,1'),
('2,1,2,2,2,2'),
('2,1'),
('1,1,2,1,2,1');
set #x = '1,1,2,1,2,1,0,1,2,1,2,1,0,1,2,1,1,1,2,1';
select s from mytable
where right(#x, length(s)) = s;
Output:
s
1,1,2,1
2,1
Fiddle: https://www.db-fiddle.com/f/r5m2hPbnmUu5VQfYvMVtir/0
You could use a LIKE trick here. For example, to check for the first string 1,1,2,1:
SELECT *
FROM yourTable
WHERE ',1,1,2,1,2,1,0,1,2,1,2,1,0,1,2,1,1,1,2,1,' LIKE '%,1,1,2,1,%';

Splitting out a single field into multiple fields

I have a table with the following fields:
id, type, date, changelog.
The changelog field has 10 useful pieces of information I would like to split out into their own fields. both new and old: name, month, year, zipcode, status
So I would like to create a table with the following fields:
id, type, date, old_name, new_name, old_month, new_month, old_year, new_year, old_zipcode, new_zipcode, old_status, new_status.
When all 5 pieces of information exist it is easy but when some are missing I can’t get it to work. Any help is appreciated.
a typical changelog field doesn't have all of these pieces of information, just what is being updated.
for example:
id type date changelog
101 upd 1/1/2019 ---!hash:ActiveSupport
name:
- Adam
- Chris
month:
- 7
- 12
status:
- 1
- 3
Which would translate to:
id type date old_name new_name old_month new_month old_year new_year old_zipcode new_zipcode old_status new_status
101 upd 1/1/19 Adam Chris 7 12 1 3
This is not a complete solution (it assumes you can already parse out the values when you know they are present), but it addresses how to handle when those values are missing:
INSERT INTO tableV2 (id, type, date, old_name, new_name, and so on....)
SELECT id, type, date
, CASE WHEN INSTR(changelog, 'name:') = 0 THEN NULL
ELSE (parse the value out here)
END AS old_name
, CASE WHEN INSTR(changelog, 'name:') = 0 THEN NULL
ELSE (parse the value out here)
END AS new_name
, and so on....
FROM tableV1
;
The parsing, while not trivial, probably won't be too difficult other than the tediousness of it. You'll need to take the found "tag" location, find the 3 newlines following it (first for the tag, latter for each value), and then use those along with other string functions such as SUBSTR, LEFT... and maybe some CHAR_LENGTH(tag string) like CHAR_LENGTH('name:') to make the parsing repeatable for each tag with minor modification.

MySQL swap numbers for letters in field

If I take a value of 12345 from MySQL and I want to display that at the front end as Mo Tu We Th Fr, how can I do that allowing for all possible combinations?
I could write a case statement but there are going to be many hundreds of combinations to cover all possible values.
The value will be anything from 1 to 7 characters long using between digits between 1 and 7 and could be in any order so 3417 should read We Th Mo Su whilst 645 should read Sa Th Fr and so on. I cannot do this in the application so have to try and figure out how to do it in MySQL. These are stored in MySQL as a varchar in a single column.
Can I use replace multiple times in the same select so something like:
REPLACE(REPLACE(REPLACE(field, '1', 'Mo '), '2', 'Tu'), '3', 'We')
or is there another way?
You can create a helper table that contains 2 columns :
1, su
2, mo
3, ...
then just join the day number to get the second column of the helper table.
If all you want to do is display this in a fronend, you can have a "dictionary" to translate the values.
Lets say for example you have a Table in the structure
tl_days
__________
id | alias
And we have some data such as
id: 1, alias : Mon
id: 2, alias : Tue
We can run a simple query to check the id against an array of numbers.
SELECT alias FROM 'tl_days' WHERE id in (1,2,3,4);
Will return the days as your abbreviations.
You should not write replace for all the values if there are multiple of them, Instead create a mapping table 1|su,2|mo ..., Then use join to fetch the 'su','mo' values from the mapping table
First you would need to ensure that the table schema data matches. If changing from numeric value to text value is acceptable.
Update table_name set column_name =
(
CASE
when column_name = 1 then 'Mo'
when column_name = 2 then 'Tu'
when column_name = 3 then 'We'
when column_name = 4 then 'Th'
when column_name = 5 then 'Fr'
End
);
Here is an SQL FIDDLE displaying such a change.

Replace last string in IP-address accornding to specific condition in PL/SQL

I've got table with fields and values:
ENTADDR (VARCHAR2) ENTIFINDEX (VARCHAR2)
18.17.16.2 1
18.17.16.53 2
18.17.16.1 3
18.17.16.54 4
I have to join 1st and 3rd record knowing 1st ENTADDR.
So how can I get 18.17.16.1 from 18.17.16.2? (last char -1). Similarly I have to join 2nd and 4th record knowing 2nd ENTADDR (18.17.16.54 from 18.17.16.53, i.e last char +1)
So I need "select" like:
Select
ENTIFINDEX from table1
where 'some transformation of ENTADDR (changing last char) '= ENTADDR
Thanks in advice!!
Is this what you are looking at
SQL> select concat (substr('18.17.16.2',1,9),substr ('18.17.16.2',-1)-1 ) as "concat val" from dual;
concat val
----------
18.17.16.1
select concat(left(ENTADDR,locate('.',ENTADDR,locate('.',ENTADDR,locate('.',ENTADDR)+1)+1)),right(ENTADDR,length(ENTADDR)-locate('.',ENTADDR,locate('.',ENTADDR,locate('.',ENTADDR)+1)+1))-ENTIFINDEX) as ipminusone from table
That searches for first second and third '.' and then subtracts the value of ENTIFINDEX from the last portion of the IP
You could also do this with a stored procedure if you're planning on doing this fairly often.

How to create a computed column name using another column's value (sql server 2008)

I need to use the value of a column in the name of a new column....this is the line I need help with:
Count([DepartmentName]) As [[DepartmentName] + "Emails"]
Code:
SELECT
[CustomerId],
#MetricMonth AS "MetricMonth",
#MetricYear AS "MetricYear",
[LeadType], [DeviceTypeId], [DepartmentName],
Count([DepartmentName]) As [[DepartmentName] + "Emails"]
FROM
[myTable]
WHERE
LeadType = #LeadType
AND _CreateDate BETWEEN #StartDateTime AND #EndDateTime
GROUP BY
[CustomerId], [LeadType], [DeviceTypeId], [DepartmentName]
The reason for the need is that the receiving table has columns labeled as such and this seems like the cleanest way to do it. There are 16 possible values for DepartmentName so I don't want to have a bunch of case statements.
Here's a sample of the result. There will be multiple groups because of DepartmentName and DeviceTypeId.
CustomerId MetricMonth MetricYear LeadType DeviceTypeId DepartmentName NewName
28590 4 2014 Email 1 New 9
36980 4 2014 Email 1 Finance 3
876 4 2014 Email 1 New 9
Thanks!
You in effect want a column name that has multiple values, ie a column with multiple names, which is just impossible in any flavor of SQL, afaik.
Short of that, you have two options:
if you really want columns with names like "Department1 Emails" then you will have to pivot the data (and you'll have to hard-code all the Department Names). If that is what you want see here.
if you just want a column called "Department Emails" with values such as "Department1 Emails: 30" then you can do this:
SELECT [DepartmentName], [DepartmentName] + ' Emails: ' + CAST(COUNT([DepartmentName]) AS VARCHAR(20))
FROM [myTable]
GROUP BY [DepartmentName]