ORDER BY Alphanumeric sort - sql

I want to ORDER BY data in the following sequence:
Number-Number
Alpha-Number
Alpha with no dash
I have the following sort:
120-1
120-2
120-10
Digital-1
Digital-10
Digital-2
Wedding
This is the order I'm looking for, except the Digital (Alpha with dash) entries are not sorted by numbers after the dash.
After many attempts, here's my current sql statement:
SELECT SessionID, Identifier FROM Session
ORDER BY
CASE
WHEN CAST(Identifier AS INTEGER) THEN SUBSTR(Identifier,0, INSTR(Identifier, '-')) + CAST(SUBSTR(Identifier, INSTR(Identifier, '-')+1, 999) AS INTEGER)
ELSE Identifier END
What am I doing wrong?
Thanks.

1) Order by strings having - in them so they appear first
2) Order by the first part before - in the strings containing - casting them as integers where applicable, Else order by the column itself
3) Order by the second part after - in the strings containing - casting them as integers where applicable, Else order by the column itself
select val
from t
order by
case when val like '%-%' then 1 else 2 end
,case when substr(val,1,instr(val,'-')-1) glob '*[0-9]*'
then cast(substr(val,1,instr(val,'-')-1) as integer)
when substr(val,1,instr(val,'-')-1) glob '*[a-zA-Z]*'
then substr(val,1,instr(val,'-')-1)
else val end
,case when val like '%-%' then cast(substr(val,instr(val,'-')+1) as integer)
else val end
SQL Fiddle

Your logic is somehow reconstructing the strings, but for the order by, you want something like this:
order by (case when CAST(Identifier AS INTEGER) <> 0 then 1
when Identifier like '%-%' then 2
else 3
end),
identifier
Note: This assumes that the numbers are never 0.

Related

Check specific integer is even

I want to know if the 4th integer in the ID, is even, or if its odd.
If the 4th number is even (if the number is either 0,2,4,6,8 I want to put the ID into a new column named 'even'
IF the 4th number is odd, the column should have the name 'Odd'
select ID as 'Female'
from Users2
where ID LIKE '%[02468]'
This shows if any of the numbers are even. I want to specify the 4th number
Try this:
select *, OddOrEven = iif(substring(ID,4,1) in ('0','2','4','6','8') , 'Even', 'Odd') from Users2
This will tell you whether the 4th character is Odd or Even.
This is of course assuming that the 4th character of ID column will be numeric.
To make it permanently part of the table, you can add a computed column as shown below.
alter table Users2
add OddOrEven as iif(substring(ID,4,1) in ('0','2','4','6','8'), 'Even', 'Odd')
Substring the character you are interested in
Convert to an int
Check whether modulus 2 returns 0 (i.e. even).
select id
, case when convert(int,substring(id, 4, 1)) % 2 = 0 then 'Even' else 'Odd' end
from Users;
Example:
select id
, case when convert(int,substring(id, 4, 1)) % 2 = 0 then 'Even' else 'Odd' end
from (values ('4545-4400'), ('4546-4400')) X (id);
Returns
id
4545-4400
Odd
4546-4400
Even
Thats assuming there is always a 4th character. If not you would need to check for it.
You were close, but only need to check a single character against a set of characters:
where Substring( Id, 4, 1 ) like '[02468]'
Note that there is no wildcard (%) in the pattern.
It can be used in an expression like:
case when Substring( Id, 4, 1 ) like '[02468]' then 'Even' else 'Odd' end as Oddity

SQL query to sort data while insert , first numbers then alphabets an last symbols

I am getting trouble to write SQL sort Query,
I have table as follows
And I want to sort above data as, First should number and then alphabets and last special symbols like following table.
First numbers should sort like 1,2,3,11,22,33
then Alphabets should sort like a ,b,c,..z
and then symbols,
like following table
I have tried many ways but still not getting correct way, please help me to write query.
You can use a CASE WHEN on the ORDER BY to create some groups:
SELECT *
FROM table_name
ORDER BY
CASE WHEN LEFT(FilterParameterValue, 1) LIKE '[0-9]' OR LEFT(FilterParameterValue, 2) LIKE '-[0-9]' OR LEFT(FilterParameterValue, 2) LIKE '+[0-9]' THEN 1 ELSE 0 END DESC, -- group for numbers
CASE WHEN ISNUMERIC(FilterParameterValue) = 1 THEN CAST(FilterParameterValue AS MONEY) ELSE NULL END ASC, -- order the numeric values
CASE WHEN LEFT(FilterParameterValue, 1) LIKE '[A-Za-z]' THEN 1 ELSE 0 END DESC, -- group for chars from A to Z (capital / non capital)
colName
demo on dbfiddle.uk
Try using regex in order by clause.. For ex
ORDER BY IF(FilterParameterValue RLIKE '^[a-z]', 1, 2), FilterParameterValue
You can try to cast your Column to Numeric Type then ordered
SELECT * FROM table_name ORDER BY TRY_CAST(Column_Name as Type)

Non-standard sort order

I have the following data in an SQL column. Column type is String. I would prefer to sort this data when I query it from the DB, but I suppose it could be organized with some Ruby magic after the SQL query is complete. There are other columns being pulled out, so this is just one of the columns that needs to be sorted.
Expenses
$3500/MONTH
$1,000.00
STANDARD CONTRACTOR
$5,000.00
The data cannot change and must be stored in the same column (the example above just test data).
I would like to organize the data by increasing number and then the rest (string) values. The expected result should be:
$1,000.00
$5,000.00
$3500/MONTH
STANDARD CONTRACTOR
or
$1,000.00
$5,000.00
STANDARD CONTRACTOR
$3500/MONTH
Option 1 (fiddle here):
select expenses from table1
order by
replace(replace(expenses, "$", ""), ",", "") regexp "[0-9.]*" desc,
case when replace(replace(expenses, "$", ""), ",", "") regexp "[0-9.]*"
then cast(replace(replace(expenses, "$", ""), ",", "") as real)
else 0
end
Option 2 (fiddle here):
select expenses from (
select expenses,
replace(replace(expenses, "$", ""), ",", "") expensesNormalized
from table1
) s
order by
expensesNormalized regexp "[0-9.]*" desc,
case when expensesNormalized regexp "[0-9.]*"
then cast(expensesNormalized as real)
else 0
end
Go for whichever runs faster.
If the existing answers work in SQLlite, then perhaps they'll work for you. Because the data is pretty ... messy ... I would tend to try to encapsulate the ugly part of this in a single method that returns a sorted array.
If you have a small number of rows like this (e.g. less than 500) then the cleaner way to sort would be to include Comparable and write a custom comparator, as nicely documented in this SO answer.
In SQL Server, you can do something like the following:
order by (case when isnumeric(col) = 1 then 1 else 0 end) desc,
(case when isnumeric(col) = 1 then cast(col as money) end),
col
For other databases, you can use regular expression matching rather than isnumeric to determine which are numbers.
Since you are using SQLite and I seem to be able to assume that all the numbers start with a '$', then something like this almost works:
order by (case when substr(col, 1, 1) = '$' then 1 else 0 end) desc,
(case when substr(col, 1, 1) = '$' then cast(col as numeric) end),
col
The problem is that "$3,500/month" is treated as a number. You can fix this with a regexp, if you have that included. Or, if the "/" defines these cases, you can use something specific like:
order by (case when substr(col, 1, 1) = '$' and col not like '%/%' then 1 else 0 end) desc,
(case when substr(col, 1, 1) = '$' and col not like '%/%' then cast(col as numeric) end),
col

Specify order of (T)SQL execution

I have seen similar questions asked elsewhere on this site, but more in the context of optimization.
I am having an issue with the order of execution of the conditions in a WHERE clause. I have a field which stores codes, most of which are numeric but some of which contain non-numeric characters. I need to do some operations on the numeric codes which will cause errors if attempted on non-numeric strings. I am trying to do something like
WHERE isnumeric(code) = 1
AND CAST(code AS integer) % 2 = 1
Is there any way to make sure that the isnumeric() executes first? If it doesn't, I get an error...
Thanks in advance!
The only place order of evaluation is guaranteed is CASE
WHERE
CASE WHEN isnumeric(code) = 1
THEN CAST(code AS integer) % 2
END = 1
Also just because it passes the isnumeric test doesn't guarantee that it will successfully cast to an integer.
SELECT ISNUMERIC('$') /*Returns 1*/
SELECT CAST('$' AS INTEGER) /*Fails*/
Depending upon your needs you may find these alternatives preferable.
Why not simply do it using LIKE?:
Where Code Not Like '%[^0-9]%'
Btw, either using my solution or using IsNumeric, there are some edge cases which might lead one to using a UDF such as 1,234,567 where IsNumeric will return 1 but Cast will throw an exception.
Why not use a CASE statement to say something like:
WHERE
CASE WHEN isnumeric(code) = 1
THEN CAST(code AS int) % 2 = 1
ELSE /* What ever else if not numeric */ END
You could do it in a case statement in the select clause, then limit by the value in an outer select
select * from (
select
case when isNum = 1 then CAST(code AS integer) % 2 else 0 end as castVal
from (
select
Case when isnumeric(code) = 1 then 1 else 0 end as isNum
from table) t
) t2
where castval = 1

how do i filter out non-numeric values in a text field in teradata?

oI have a teradata table with about 10 million records in it, that stores a numeric id field as a varchar. i need to transfer the values in this field to a bigint column in another table, but i can't simply say cast(id_field as bigint) because i get an invalid character error. looking through the values, i find that there could be a character at any position in the string, so let's say the string is varchar(18) i could filter out invalid rows like so :
where substr(id_field,1,1) not in (/*big,ugly array of non-numeric chars*/)
and substr(id_field,2,1) not in (/*big,ugly array of non-numeric chars*/)
etc, etc...
then the cast would work, but this is not feasible in the long run. it's slow and if the string has 18 possible characters, it makes the query unreadable. how can i filter out rows that have a value in this field that will not cast as a bigint without checking each character individually for an array of non-numeric characters?
example values would be
123abc464
a2.3v65
a_356087
........
000000000
BOB KNIGHT
1235468099
the values follow no specific patterns, I simply need to filter out the ones that contain ANY non-numeric data.
123456789 is okay but 123.abc_c3865 is not...
Starting with TD14 Teradata added some functions, now there are multiple ways, e.g.:
WHERE RTRIM(col, '0123456789') = ''
But the easiest way is TO_NUMBER, which returns NULL for bad data:
TO_NUMBER(col)
The best that I've ever managed is this:
where char2hexint(upper(id_field)) = char2hexint(lower(id_field))
Since upper case characters give a different hex value to lower case ones, this will ensure that you have no alphabetical characters, but will still leave you with underscores, colons and so forth. If this doesn't meet your requirements, you may need to write an UDF.
could we also try to divide the values in the field by some integer "if divided then must be a number and if not and throws some error,then must have some character...." guess this would be lot fast as has just mathematics involved...
I've faced the same issue to try to exclude alpha characters from street address house numbers. The following will work if you don't mind concatanating all the numeric numbers together......
It checks if the upper of a string equals the lower of the string, if so it's a number, if not it becomes null.
select cast(case when upper(substring('12E'from 1 for 1)) = lower(substring('12E'from 1 for 1)) then substring('12E'from 1 for 1) else null end ||
case when upper(substring('12E'from 2 for 1)) = lower(substring('12E'from 2 for 1)) then substring('12E'from 2 for 1) else null end ||
case when upper(substring('12E'from 3 for 1)) = lower(substring('12E'from 3 for 1)) then substring('12E'from 3 for 1) else null end ||
case when upper(substring('12E'from 4 for 1)) = lower(substring('12E'from 4 for 1)) then substring('12E'from 4 for 1) else null end ||
case when upper(substring('12E'from 5 for 1)) = lower(substring('12E'from 5 for 1)) then substring('12E'from 5 for 1) else null end ||
case when upper(substring('12E'from 2 for 1)) = lower(substring('12E'from 2 for 1)) then substring('12E'from 2 for 1) else null end
as integer)
Try using this code segment
WHERE id_Field NOT LIKE '%[^0-9]%'
I found lins314159 answer to be very helpful with a similar issue. It may be an old thread but for what it's worth, I used:
char2hexint(upper(id_field)) = char2hexint(lower(id_field)) AND substr(id_field,1,1) IN ('1' to '9')
to successfully cast the remaining VARCHAR results to INT
SELECT customer_id
FROM t
WHERE UPPER(customer_id)(CASESPECIFIC) <>
LOWER(customer_id)(CASESPECIFIC);
This works perfectly fine to check whether the values in a numeric field is non-numeric.
SELECT id_field
WHERE oTranslate(id_field, '0123456789','')<>'';
This works well for me! It reveals any id_field containing a non-numeric value