SQL Server SELECT query ordering by substring - sql-server

I have a column in a SQL Server table that has the following rows:
MyColumn : C1_xxx1,C2_xxx1,C3_xxx1,C1_xxx2,C1_xxx3,C3_xxx2 etc
It is a text column that contains strings that have the following format: CY_mystring where Y is a number from 1 to 5, followed by the '_' character then mystring that can have any value.
Is there a way to make a select return this column ordered as following:
C1_xxx1
C1_xxx2
C1_xxx3
......
C1_xxxn
C2_xxx1
......
C2_xxxn
C3_xxx1
.......
C3_xxxn
etc
Ordered by the CY_ substring.
thank you

This should do it .. (order first by the first two chars, and then by the last char (assuming that the final n is always one digit long))
SELECT
Column1
FROM
TABLENAME
ORDER BY
LEFT(Column1,2) ASC,
RIGHT(Column1,1) ASC

You say that Y is a number from 1 to 5 it's always one character long. Assuming the format is xY_xxxZ, you can order on Y then Z like:
order by
substring(MyColumn,2,1) -- Second digit
, right(MyColumn,1) -- Last digit
If Z can be longer than one character (i.e. 10 or higher) you can use pathindex to determine the number of digits at the end:
order by
substring(MyColumn,2,1) -- Second digit
, right(MyColumn, patindex('%[^0-9]%', reverse(MyColumn))-1) -- Digits at end

Related

How to mask some digit using SQL Select

I have a column named Number
Suppose a value is 12345678997
and I want to output as *******8997, that means all leading digits will be masked by * except the last 4 digits
how can I achieve this using SQL Server Select ?
Try this:
declare #i bigint = '12345678997'
select stuff(#i,1,len(#i)-4,'*******')
Output:
*******8997
Using REPLICATE you can generate a string with a given number of the same character.
Then just add the last four digits to that.
select
Number,
concat(replicate('*',len(Number)-4), right(Number,4)) as MaskedNumber
from YourTable

SQL Server - How to get last numeric value in the given string

I am trying to get last numeric part in the given string.
For Example, below are the given strings and the result should be last numeric part only
SB124197 --> 124197
287276ACBX92 --> 92
R009321743-16 --> 16
How to achieve this functionality. Please help.
Try this:
select right(#str, patindex('%[^0-9]%',reverse(#str)) - 1)
Explanation:
Using PATINDEX with '%[^0-9]%' as a search pattern you get the starting position of the first occurrence of a character that is not a number.
Using REVERSE you get the position of the first non numeric character starting from the back of the string.
Edit:
To handle the case of strings not containing non numeric characters you can use:
select case
when patindex(#str, '%[^0-9]%') = 0 then #str
else right(#str, patindex('%[^0-9]%',reverse(#str)) - 1)
end
If your data always contains at least one non-numeric character then you can use the first query, otherwise use the second one.
Actual query:
So, if your table is something like this:
mycol
--------------
SB124197
287276ACBX92
R009321743-16
123456
then you can use the following query (works in SQL Server 2012+):
select iif(x.i = 0, mycol, right(mycol, x.i - 1))
from mytable
cross apply (select patindex('%[^0-9]%', reverse(mycol) )) as x(i)
Output:
mynum
------
124197
92
16
123456
Demo here
Here is one way using Patindex
SELECT RIGHT(strg, COALESCE(NULLIF(Patindex('%[^0-9]%', Reverse(strg)), 0) - 1, Len(strg)))
FROM (VALUES ('SB124197'),
('287276ACBX92'),
('R009321743-16')) tc (strg)
After reversing the string, we are finding the position of first non numeric character and extracting the data from that position till the end..
Result :
-----
124197
92
16

Oracle: Check if number column contains a value from a formatted string of numbers

In my local table, I am try to check if an Oracle Number column called JOBNUMBER has a value that exists in a string parameter. Technically I am passing in the string as a stored procedure nvarchar2 parameter, but for simplicity, I hardcoded the string in my Query below:
SELECT FIRST_NAME, JOB_NUMBER
FROM JOBTABLE
WHERE TO_CHAR(JOB_NUMBER) IN ('00052, 00048');
When Oracle runs the query above, it returns no values even though 00052 is a number value in the table column for JOB_NUMBER. I'm thinking that it checks for the whole string ('00052, 00048') in JOB_NUMBER and can't find it, so it returns no values. The string will contain different values each time, and there will several numbers (of type string) in that string.
Does anyone know how to do this?
The trick is to keep the leading zeroes of the number when comparing to the string, then looping through the string to compare. Here a CTE is used is to simulate creating a numeric job number and a string to search. The TO_CHAR function makes sure to preserve the leading zeroes and the FM format removes the leading space that TO_CHAR leaves for the sign. CONNECT BY loops through the elements for the count of the delimiter + 1 times, keeping the count in the value in 'LEVEL'. This value is used in REGEXP_SUBSTR to iterate through the elements to compare the converted numeric value to each element to see if a match is found. Note this regular expression allows for NULL elements should you need to know which item in the list is your match.
SQL> with tbl(job_nbr_in, job_str_in) as (
select 00052, '00052, 00048' from dual
)
select --level element_nbr,
to_char(job_nbr_in, 'FM00000') search_for, job_str_in in_string,
regexp_substr(job_str_in, '(.*?)(, |$)', 1, level, NULL, 1) found
from tbl
where to_char(job_nbr_in, 'FM00000') = regexp_substr(job_str_in, '(.*?)(, |$)', 1, level, NULL, 1)
connect by level <= regexp_count(job_str_in, ',')+1;
SEARCH_FOR IN_STRING FOUND
---------- ------------ ------------
00052 00052, 00048 00052
If you are not sure if you will always have a space after the comma, remove spaces with REPLACE and adjust the delimiter in REGEXP_SUBSTR:
with tbl(job_nbr_in, job_str_in) as (
select 00052, '00052, 00048' from dual
)
select to_char(job_nbr_in, 'FM00000') search_for, job_str_in in_string,
regexp_substr(replace(job_str_in, ' '), '(.*?)(,|$)', 1, level, NULL, 1) found
from tbl
where to_char(job_nbr_in, 'FM00000') = regexp_substr(replace(job_str_in, ' '), '(.*?)(,|$)', 1, level, NULL, 1)
connect by level <= regexp_count(job_str_in, ',')+1;

Adding the value in column of SQL Server 2012

I need to add two zero in POS data to make it 14th character numbers because TV UPC has 14th character numbers UPC.
For example
Table 1
POS UPC
------------
123456789012
Table 2
TV UPC
--------------
00123456789012
I have to make it POS UPC 14 character number by adding two zero at the beginning of the number to compare exact match.
Prefix the number with 14 0s and select 14 characters from right which will give you desired output
DECLARE #Number varchar(100)='123456789012'
SELECT RIGHT('00000000000000'+#Number,14)
Output
00123456789012
Replace variable with your column name.
Fiddle here : http://sqlfiddle.com/#!3/9f1d32/1

SQL Server: sort a column numerically if possible, otherwise alpha

I am working with a table that comes from an external source, and cannot be "cleaned". There is a column which an nvarchar(20) and contains an integer about 95% of the time, but occasionally contains an alpha. I want to use something like
select * from sch.tbl order by cast(shouldBeANumber as integer)
but this throws an error on the odd "3A" or "D" or "SUPERCEDED" value.
Is there a way to say "sort it like a number if you can, otherwise just sort by string"? I know there is some sloppiness in that statement, but that is basically what I want.
Lets say for example the values were
7,1,5A,SUPERCEDED,2,5,SECTION
I would be happy if these were sorted in any of the following ways (because I really only need to work with the numeric ones)
1,2,5,7,5A,SECTION,SUPERCEDED
1,2,5,5A,7,SECTION,SUPERCEDED
SECTION,SUPERCEDED,1,2,5,5A,7
5A,SECTION,SUPERCEDED,1,2,5,7
I really only need to work with the
numeric ones
this will give you only the numeric ones, sorted properly:
SELECT
*
FROM YourTable
WHERE ISNUMERIC(YourColumn)=1
ORDER BY YourColumn
select
*
from
sch.tbl
order by
case isnumeric(shouldBeANumber)
when 1 then cast(shouldBeANumber as integer)
else 0
end
Provided that your numbers are not more than 100 characters long:
WITH chars AS
(
SELECT 1 AS c
UNION ALL
SELECT c + 1
FROM chars
WHERE c <= 99
),
rows AS
(
SELECT '1,2,5,7,5A,SECTION,SUPERCEDED' AS mynum
UNION ALL
SELECT '1,2,5,5A,7,SECTION,SUPERCEDED'
UNION ALL
SELECT 'SECTION,SUPERCEDED,1,2,5,5A,7'
UNION ALL
SELECT '5A,SECTION,SUPERCEDED,1,2,5,7'
)
SELECT rows.*
FROM rows
ORDER BY
(
SELECT SUBSTRING(mynum, c, 1) AS [text()]
FROM chars
WHERE SUBSTRING(mynum, c, 1) BETWEEN '0' AND '9'
FOR XML PATH('')
) DESC
SELECT
(CASE ISNUMERIC(shouldBeANumber)
WHEN 1 THEN
RIGHT(CONCAT('00000000',shouldBeANumber), 8)
ELSE
shouoldBeANumber) AS stringSortSafeAlpha
ORDEER BY
stringSortSafeAlpha
This will add leading zeros to all shouldBeANumber values that truly are numbers and leave all remaining values alone. This way, when you sort, you can use an alpha sort but still get the correct values (with an alpha sort, "100" would be less than "50", but if you change "50" to "050", it works fine). Note, for this example, I added 8 leading zeros, but you only need enough leading zeros to cover the largest possible integer in your column.

Resources