sort multi value column in oracle table - oracle

I'm trying to sort on a column in oracle table. The column value is 'M013,M007,M019,YYY,M018,XXX,999'. I'm trying to sort the values with in the column before comparing it to another column which already has the data sorted. I've tried multiple hash/MD5 and few other options, but didn't help.
Any help is appreciated !!

What you have is a comma separated string of random elements. As you indicated the listagg function can sort the results. I think your best bet then is to parse the string into individual elements then let listagg rebuild the string with sorted elements. (See fiddle)
with test(str) as
( select 'M013,M007,M019,YYY,M018,XXX,999' from dual)
select listagg(estr,',') within group (order by estr)
from (select regexp_substr(str,'[^,]+', 1, level) estr
from test connect by regexp_substr(str, '[^,]+', 1, level) is not null
) ;

Related

Oracle APEX apex_string.split order by

Does apex_string.split always guarantee that the order of the rows returned is the order of the characters of the string ?
Can I rely on the rownum to always correspond to 1 for the first character of the split string ?
or do I need to add a order by rownum ?
What is the method to get the rows in the same order of the characters of the string ?
My requirement is to insert the rows returned by apex_string.split in the same order as the characters of the string.
I am currently executing the below, will this maintain the character order ?
select t.column_value value, rownum seq
from table(apex_string.split('test','')) t
bulk collect into ins_arr;
for i in ins_arr.first..ins_arr.last
loop
/* execute insert statement */
insert into table (seq, value )
values (ins_arr.seq,ins_arr.value);
end loop
The insert should result in
seq
value
1
t
2
e
3
s
4
t
Thank you in advance,
I don't think it's guaranteed, becuase if it was, it would be in the documentation. But I think you can accomplish what you want by changing your routine. (Note, I have not verified this.)
insert into table (seq, value)
select t.column_value value,
row_number() over (order by t.column_value)
from table(apex_string.split('test','')) t
I think you can do the same with rownum, but I'm never 100% sure what order the rownum and the order by happen in.

Trying to display top 3 amount from a table using sql query in oracle 11g..column is of varchar type

Am trying to list top 3 records from atable based on some amount stored in a column FTE_TMUSD which is of varchar datatype
below is the query i tried
SELECT *FROM
(
SELECT * FROM FSE_TM_ENTRY
ORDER BY FTE_TMUSD desc
)
WHERE rownum <= 3
ORDER BY FTE_TMUSD DESC ;
o/p i got
972,9680,963 -->FTE_TMUSD values which are not displayed in desc
I am expecting an o/p which will display the top 3 records of values
That should work; inline view is ordered by FTE_TMUSD in descending order, and you're selecting values from it.
What looks suspicious are values you specified as the result. It appears that FTE_TMUSD's datatype is VARCHAR2 (ah, yes - it is, you said so). It means that values are sorted as strings, not numbers - and it seems that you expect numbers. So, apply TO_NUMBER to that column. Note that it'll fail if column contains anything but numbers (for example, if there's a value 972C).
Also, an alternative to your query might be use of analytic functions, such as row_number:
with temp as
(select f.*,
row_number() over (order by to_number(f.fte_tmusd) desc) rn
from fse_tm_entry f
)
select *
from temp
where rn <= 3;

How to order by field mixed with string and number in Oracle?

These are the field (crane_no) values to be sorted
QC11QC10QC9
I tried the following query:
select * from table order by crane_no DESC
but query results does not give in an order because the field is mixed with staring and number (Example:QC12).
I get following results for above query:
QC9QC11QC10
I want the results to be in order (QC9, QC10, QC11). Thanks
If the data isn't huge, I'd use a regex order by clause:
select
cran_no
from your_table
order by
regexp_substr(cran_no, '^\D*') nulls first,
to_number(regexp_substr(cran_no, '\d+'))
This looks for the numbers in the string, so rows like 'QCC20', 'DCDS90' are ordered properly; it also takes care of nulls.
One approach is to extract the numeric portion of the crane_no columns using SUBSTR(), cast to an integer, and order descending by this value.
SELECT *
FROM yourTable
ORDER BY CAST(SUBSTR(crane_no, 3) AS INT) DESC
Note that I assume in my answer that every entry in crane_no is prefixed with the fixed width QC. If not, then we would have to do more work to identify the numerical component.
select ...
order by to_number( substr( crane_no,3 )) desc

Oracle invalid number in clause

I'm struggling with getting a query to work, and I could really use some help. We have an in house app that we use for building small web apps where I work. It's basically a drag and drop GUI. There's functionality built in to access query string values using the key.
I'm passing a comma separated list of values into a page through the query string. I'm then trying to use the list of values as part of an in clause in a query.
I can see that the value is correct in the query string.
orders=1,2,3
Here's the specific part of the query
"AND OrderNumber IN (this is where it maps from the query string)
I've tried running similar queries in Toad, and I think I've found the issue. It's giving an invalid number error, and I think it's wrapping the query string value in single quotes. I can replicate the error when I do "AND OrderNumber IN ('1,2,3')" in Toad.
Here's where I get really confused. The following works in Toad.
"AND OrderNumber IN ('1','2','3')"
So I tried recreating that by doing
select replace('1,2,3', ',', chr(39)||','||chr(39)) from dual;
I have confirmed that returns '1','2','3' in Toad.
However, I still get an Invalid Number error when I run the following in Toad.
AND OrderNumber IN (replace('1,2,3', ',', chr(39)||','||chr(39))
I've been racking my brain over this, and I can't figure it out. It seems to me that if "AND OrderNumber IN ('1','2','3')" works, and replace('1,2,3', ',', chr(39)||','||chr(39)) returns '1','2','3', that "AND OrderNumber IN (replace('1,2,3', ',', chr(39)||','||chr(39))" should work.
Any help you might be able to offer on this would be greatly appreciated. I know the rest of the query works. That's why I didn't post it. I'm just stuck on trying to get this IN clause working.
A change to phonetic_man's answer that will allow for NULL elements in the list. The regex format of '[^,]+' for parsing delimited lists does not handle NULL list elements and will return an incorrect value if one exists and thus its use should be avoided. Change the original by deleting the number 2 for instance and see the results. You will get a '3' in the 2nd element's position! Here's a way that handles the NULL and returns the correct value for the element:
SELECT TRIM(REGEXP_SUBSTR(str, '(.*?)(,|$)', 1, LEVEL, NULL, 1)) str
FROM ( SELECT '1,,3,4' str FROM dual )
connect by level <= regexp_count(str, ',') + 1;
See here for more info and proof: https://stackoverflow.com/a/31464699/2543416
Can you try the following query.
SELECT * FROM orders
WHERE orderno IN
(
SELECT TRIM(REGEXP_SUBSTR(str, '[^,]+', 1, LEVEL)) str
FROM ( SELECT '1,2,3,4' str FROM dual )
CONNECT BY INSTR(str, ',', 1, LEVEL - 1) > 0
)
The inline query splitting the string in different rows. So, on executing it you will get the following result.
SELECT trim(regexp_substr(str, '[^,]+', 1, LEVEL)) str
FROM ( SELECT '1,2,3,4' str FROM dual )
CONNECT BY instr(str, ',', 1, LEVEL - 1) > 0
1
2
3
4
Now, passing this result to the main query IN clause should work.
I think the desired clause to be built is:
AND OrderNumber IN (1,2,3)
A numeric list. The example you tested:
AND OrderNumber IN ('1','2','3')
works because an implicit conversion from a VARCHAR2 to a NUMBER is occurring for each element in the list.
The following clause will not work because no implicit conversion of the string '1,2,3' can be made (note the clause has a single string element):
AND OrderNumber IN ('1,2,3')
When doing a replace, you are converting the single string: 1,2,3 with the single string: 1','2','3 and this single string cannot be implicitly converted to a number.

oracle truncates the value after saving an id with precisions?

I have a table. it has a column with datatype NUMBER(38,20). it is an id column. out application generates the id. i am trying to insert record with an id value of 105.00010. but it inserts only 105.0001. May i know the reason why it is truncating one value(0). it porperly inserts records from 105.00001 to 105.00009. while inserting 105.00010 it is truncating. Please help me.
column size is **NUMBER(38,20)**
Thanks!
See the following test case:
WITH data_values
AS (SELECT 105.0001 AS test_val FROM dual
UNION ALL
SELECT 105.00010 AS test_val FROM dual)
SELECT test_val,
TO_NUMBER(test_val, '999.99999') AS NUM,
TO_CHAR(test_val, '999.99999') AS STR
FROM data_values;
Results in:
TEST_VAL NUM STR
105.0001 105.0001 105.00010
105.0001 105.0001 105.00010
The value after the final non zero digit is irrelevent to Oracle. Both your numbers are equivalent.
The rightmost zeros after the decimal are insignificant, so the value is not truncated, it is still the same value.
If you need it to stay the same you may need to treat the value as a varchar2.

Resources