I need to fetch records based on particular type(FFRT-TR= ) and then replace it. For example below are the record types
20017546 FFRT-TR= 3456
TT:SX 2398 FFRT-TR=6532
I need to fetch records which contains FFRT-TR= and then replace the whole the of FFRT-TR=3456 Required Output based on the above examples: 20017546(for 1st example) 2398(for 2nd example)
Please help. Thanks in advance
Something like this? Oracle-ish (you didn't specify the database you use), but - hopefully - you'll be able to rewrite it if necessary.
SQL> with test (col) as
2 (select '20017546 FFRT-TR= 3456' from dual union
3 select 'TT:SX 2398 FFRT-TR=6532' from dual
4 )
5 select
6 col,
7 replace(regexp_substr(col, '\d+ FFRT-TR='), 'FFRT-TR=', '') result
8 from test;
COL RESULT
----------------------- ----------------------------------------------------
20017546 FFRT-TR= 3456 20017546
TT:SX 2398 FFRT-TR=6532 2398
SQL>
Related
So i have a column that is number by type, there are values in there with numbers like 8, 15.0, 89.1 or null. I need to add a decimal spot to them so they would look like 8.00, 15.00, 89.10 and the nulls replaced with 0.00.( there are hundreds of number values not just the 4 examples) I figured I needed to do an update with a case, the null part is simple enough
update table
set cost = case
when null then 0.00
not sure how to tackle the other three situations, any help is much appreciated !!
So i have a column that is number by type
To me, it looks like a presentation issue, not storage. Justin tried to convince you that you don't have to do anything about it, I suggest you re-read what he said.
Table looks like this:
SQL> create table test (col) as
2 select 8 from dual union all
3 select 15.0 from dual union all
4 select 89.1 from dual union all
5 select null from dual; --> only NULL should be replaced by 0
Table created.
SQL> update test set col = 0 where col is null;
1 row updated.
SQL>
If you don't do anything, this is the result:
SQL> select * from test;
COL
----------
8
15
89,1
0
SQL>
As of presentation: it depends on a tool you use. For example: if it were SQL*Plus, you could format the column as
SQL> column col format 90D00
SQL> select * from test;
COL
------
8,00
15,00
89,10
0,00
SQL>
Comma is a decimal character in my database; change it to a dot:
SQL> alter session set nls_numeric_characters = '.,';
Session altered.
SQL> select * from test;
COL
------
8.00
15.00
89.10
0.00
SQL>
Or, in any tool, use the TO_CHAR function with appropriate format mask:
SQL> select col, to_char(col, '90D00', 'nls_numeric_characters = ''.,''') result from test;
COL RESULT
---------- ------
8 8.00
15 15.00
89,1 89.10
0 0.00
SQL>
Or, if it is some GUI tool (be it Oracle Forms, Reports, Apex, ...), it contains the Format mask property you should use for the same purpose - presentation - and put 90D00 into it to format value displayed to end users.
Therefore, once again: there's nothing wrong with values stored in that column; it is just about the way users will see them.
I have a table like below
ID NUMBER 1 NUMBER 2 NUMBER 3 LOC
1-14H-4950 0616167 4233243 CA
A-522355 1234567 TN
A-522357 9876543 WY
A-522371 1112223 WA
A-522423 1234567 2345678 1234567 NJ
A-A-522427 9876543 6249853 6249853 NJ
and I have a bunch of values (1234567, 9876543, 0616167, 1112223, 999999...etc) which will be used in where clause, if a value from where clause found in one of the three Number columns (Number 1 or Number 2 Number 3) then I will have to write that to output1 (its like VLOOKUP of Excel).
If the value is found in more than one of the three columns then it will be different output2 with a flag as MultipleMatches. If the value is not found in any of the three columns then it should be in Output2 with flag as No Match. I tried using self join and or clauses, but not able to get what I want.
I want to write the SQL to generate both outputs. Outputs will include all the columns from the above table. For eg:
Output 1 from above sample data will look like
ID NUMBER 1 NUMBER 2 NUMBER 3 LOC
1-14H-4950 0616167 4233243 CA
A-522371 1112223 WA
Output 2 will be like:
ID NUMBER 1 NUMBER 2 NUMBER 3 LOC Flag
A-522423 1234567 2345678 1234567 NJ Multiple Match
A-A-522427 9876543 6249853 6249853 NJ Multiple Match
1234 No Match
I want to write the SQL to generate both outputs.
One SELECT operator cannot produce two output sets.
The main question is, why split the output when that the difference is only in the FLAG column? If you really need two different output of the result, then you can do this:
(Rightly) create a common cursor for the query, where the FLAG column will be calculated and split the output screens already in the UI.
drop table test_dt;
create table test_dt as
select '1-14h-4950' id,null num1,616167 num2,4233243 num3,'ca' loc from dual
union all
select 'a-522355',null ,1234567,null,'tn' from dual union all
select 'a-522357',null ,9876543,null,'wy' from dual union all
select 'a-522371',null ,1112223,null,'wa' from dual union all
select 'a-522423',1234567,2345678,1234567,'nj' from dual union all
select 'a3-522423',null,null,null,'nj' from dual union all
select 'a-a-522427',9876543,6249853,6249853,'nj' from dual;
--
select
d.*,
case when t.cc_ndv=0 and t.cc_null=3 then 'Not matching'
when t.cc_ndv=(3-t.cc_null) then 'Once'
else 'Multiplay match'
end flag
--t.cc_ndv,
--t.cc_null
from test_dt d ,lateral(
select
count(distinct case level when 1 then num1
when 2 then num2
when 3 then num3
end ) cc_ndv,
count(distinct case level when 1 then nvl2(num1,null,1)
when 2 then nvl2(num2,null,2)
when 3 then nvl2(num3,null,3)
end ) cc_null
from dual connect by level<=3 and sys_guid()is not null
) t;
Or
create a procedure(see to dbms_sql.return_result) that returns a some data sets.
Process these data of cursors / datasets separately.
I want to get a list ip addresses whose last 3 digits don't fall in the range 0 to 200. I tried using REGEXP_LIKE as below. But it is giving me wrong result.
select * from ip_data
where REGEXP_LIKE(substr(ip_address,instr(ip_address,'.',1,3)+1),'[^0-200]');
It seems to have matched each digits with 0-200 numbers individually.
I want to use only REGEXP_LIKE as I've to take the range from another table where it is stored in the format [0-200].
Any suggestions would be of great help.
Using REGEXP_SUBSTR:
SQL> WITH DATA AS(
2 SELECT '127.0.0.1' ip FROM dual UNION ALL
3 SELECT '127.0.0.201' ip FROM dual
4 )
5 SELECT * FROM DATA
6 WHERE REGEXP_SUBSTR(ip,'[[:digit:]]{1,3}',1, 4)
7 NOT BETWEEN 0 AND 200
8 /
IP
-----------
127.0.0.201
SQL>
Using simple SUBSTR:
SQL> WITH DATA AS(
2 SELECT '127.0.0.1' ip FROM dual UNION ALL
3 SELECT '127.0.0.201' ip FROM dual
4 )
5 SELECT * FROM DATA
6 WHERE to_number(substr(ip,instr(ip,'.',1,3)+1))
7 NOT BETWEEN 0 AND 200
8 /
IP
-----------
127.0.0.201
SQL>
I would go with the simple SUBSTR approach since it is less resource consuming, less CPU utilization, thus better performance.
You don't need regular expression for that:
to_number(substr(ip_address,instr(ip_address,'.',1,3)+1)) not between 0 and 200
Something like this should works:
select ip_address from ip_data
where NOT REGEXP_LIKE(ip_address,'\.(([0-9])|([1-9][0-9])|([1][0-9][0-9])|(200))$');
I tried to find solution for this problem for some time but without success so any help would be much appreciated. List of IDs needs to be compared against a table and find out which records exist (and one of their values) and which are non existent. There is a list of IDs, in text format:
100,
200,
300
a DB table:
ID(PK) value01 value02 value03 .....
--------------------------------------
100 Ann
102 Bob
300 John
304 Marry
400 Jane
and output I need is:
100 Ann
200 missing or empty or whatever indication
300 John
Obvious solution is to create table and join but I have only read access (DB is closed vendor product, I'm just a user). Writing a PL/SQL function also seems complicated because table has 200+ columns and 100k+ records and I had no luck with creating dynamic array of records. Also, list of IDs to be checked contains hundreds of IDs and I need to do this periodically so any solution where each ID has to be changed in separate line of code wouldn't be very useful.
Database is Oracle 10g.
there are many built in public collection types. you can leverage one of them like this:
with ids as (select /*+ cardinality(a, 1) */ column_value id
from table(UTL_NLA_ARRAY_INT(100, 200, 300)) a
)
select ids.id, case when m.id is null then '**NO MATCH**' else m.value end value
from ids
left outer join my_table m
on m.id = ids.id;
to see a list of public types on your DB, run :
select owner, type_name, coll_type, elem_type_name, upper_bound, precision, scale from all_coll_types
where elem_type_name in ('FLOAT', 'INTEGER', 'NUMBER', 'DOUBLE PRECISION')
the hint
/*+ cardinality(a, 1) */
is just used to tell oracle how many elements are in our array (if not specified, the default will be an assumption of 8k elements). just set to a reasonably accurate number.
You can transform a variable into a query using CONNECT BY (tested on 11g, should work on 10g+):
SQL> WITH DATA AS (SELECT '100,200,300' txt FROM dual)
2 SELECT regexp_substr(txt, '[^,]+', 1, LEVEL) item FROM DATA
3 CONNECT BY LEVEL <= length(txt) - length(REPLACE(txt, ',', '')) + 1;
ITEM
--------------------------------------------
100
200
300
You can then join this result to the table as if it were a standard view:
SQL> WITH DATA AS (SELECT '100,200,300' txt FROM dual)
2 SELECT v.id, dbt.value01
3 FROM dbt
4 RIGHT JOIN
5 (SELECT to_number(regexp_substr(txt, '[^,]+', 1, LEVEL)) ID
6 FROM DATA
7 CONNECT BY LEVEL <= length(txt) - length(REPLACE(txt, ',', '')) + 1) v
8 ON dbt.id = v.id;
ID VALUE01
---------- ----------
100 Ann
300 John
200
One way of tackling this is to dynamically create a common table expression that can then be included in the query. The final synatx you'd be aiming for is:
with list_of_values as (
select 100 val from dual union all
select 200 val from dual union all
select 300 val from dual union all
...)
select
lov.val,
...
from
list_of_values lov left outer join
other_data t on (lov.val = t.val)
It's not very elegant, particularly for large sets of values, but compatibility with a database on which you might have few privileges is very good.
I am putting a bit of SQL into an Oracle script, if I run the Vanilla SQL i get the correct output of one single returned value/record. However in my custom function I get the value I am looking for returned as many times as there are records. Here is an example of what I have.
create function EXAMPLE_FUNCTION (passedID in NUMBER)
return NUMBER
IS
returnValue NUMBER;
BEGIN
SELECT "TABLE1"."ID" INTO returnValue
FROM "TABLE1" WHERE "TABLE1"."ID" = passedID;
RETURN returnValue;
END;
So if TABLE1 has 20 records I will get the record with ID 1 returned 20 times,
I am not sure where its going wrong, but I'm sure its simple!
You are probably calling the function like this:
select EXAMPLE_FUNCTION (1)
from my_table
Call it without the from:
select EXAMPLE_FUNCTION (1)
EDIT:
As pointed by Shannon Oracle requires the from clause so I searched and found examples using the dual table:
select EXAMPLE_FUNCTION (1)
from dual
Just do something like: SELECT EXAMPLE_FUNCTION(1) FROM dual;
Would something like the below work in your function?
Select COUNT(*) into returnValue
from TABLE1
where Table1.ID = passedID;
What value are you using for passedID? If you want to get soemthing different out for each row you need to pass something different in.
Compare these two function calls. First a fixed value:
SQL> select example_function(1) from table1
2 /
EXAMPLE_FUNCTION(1)
-------------------
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
20 rows selected.
SQL>
Then using the table column to supply the parameter:
SQL> select example_function(id) from table1
2 /
EXAMPLE_FUNCTION(ID)
--------------------
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
20 rows selected.
SQL>