WHERE clause that finds in 123xxx digits - sql

I try to search all rows that contain
123000 - 123xxx
So the last three are unknown but must be filled up.
So I dont want to find for example
12300 or 1230000

select * from your_table
where some_column between 123000 and 123999

If the value is a number, then just use:
where value >= 123000 and value < 124000
If value is a string:
where char_length(value) = 6 and left(value, 3) = '123'

For Firebird version 2.1 and above
select * from table_name
where
(BIN_AND(table_name.field_name,123000) = 123000)
in stored procedure with parameter
select * from table_name
where
(BIN_AND(table_name.field_name,:p) = :p)

If your sure the field will always be an int, you could use
WHERE Field LIKE '123___'
Doc for _ can be found here: here
In short, _ is a single wildcard character, so on a field which can only be an int, this should match 123000 to 123999
This could also be useful if you have to find any reference to 123 where the last 3 values could be anything, including characters
Regards,
Jamie

Related

Where x character equal value

How can I select records where in the column Value the 5th character is letter A?
For example the following records:
ID Value
-------------------------
1 1234A5636A6363
2 1234A4343B6363
3 1234B5353A6363
if I run
select * from table
where Value like '%A%'
this will return all records
but all I want is the first 2 where the 5th character is A, regardless if there are more A characters in the text or not
select *
from your_table
where substring(Value, 5, 1) = 'A'
The LIKE operator, in addition to %, which matches any number of any character, can use _, which matches any one single character. You may try:
SELECT *
FROM yourTable
WHERE Value LIKE '____A%'; -- 4 underscores here
use like below by using _(underscore)
LIKE '____A%'
SQL Server
select *
from YourTableName
where CHARINDEX('A', ColumnName) = 5
Note:- This finds where string 'A' starts at position 5
AND specify Your ColumnName

How to check the last two digits?

SUBBIS
SUBB1D
SUBBD3
SUBB12
In above values, how can I check the last two digits (IS, 1D, D3, 12) are numbers using a sql code?
Do you mean to fetch those values? You can do that with like:
where column like '%[0-9][0-9]'
If you need to ensure that the values always end with 2 numbers, you can do it with similar check constraint.
To check the last two digits are numbers in column, you can use the following script.
... WHERE ISNUMERIC(RIGHT(your_column,2)) = 1
Here RIGHT(your_column,2) will return the last two digits from the string.
or
SELECT ISNUMERIC(RIGHT(your_column,2))
will return 1 (if its number) otherwise 0
You can do it this way:
SELECT MyId,
ISNUMERIC(RIGHT(MyColumn,2)) -- your column to check last 2 (if numeric)
FROM (
----- replace with your table
SELECT 1 MyId,'SUBBIS' MyColumn UNION SELECT 2,'SUBB1D' UNION
SELECT 3,'SUBBD3' UNION SELECT 4,'SUBB12'
----- replace with your table
) A
Hope it helps. :)
You can use like and _ "underscore" to get last one digits record columName
SELECT columName FROM sub WHERE columName LIKE "SUBB__" ;
Record :
columName
SUBBIS
SUBB1D
SUBBD3
SUBB12
SUBBBA

Determine if zip code contains numbers only

I have a field called zip, type char(5), which contains zip codes like
12345
54321
ABCDE
I'd like to check with an sql statement if a zip code contains numbers only.
The following isn't working
SELECT * FROM S1234.PERSON
WHERE ZIP NOT LIKE '%'
It can't work because even '12345' is an "array" of characters (it is '%', right?
I found out that the following is working:
SELECT * FROM S1234.PERSON
WHERE ZIP NOT LIKE ' %'
It has a space before %. Why is this working?
If you use SQL Server 2012 or up the following script should work.
DECLARE #t TABLE (Zip VARCHAR(10))
INSERT INTO #t VALUES ('12345')
INSERT INTO #t VALUES ('54321')
INSERT INTO #t VALUES ('ABCDE')
SELECT *
FROM #t AS t
WHERE TRY_CAST(Zip AS NUMERIC) IS NOT NULL
Using answer from here to check if all are digit
SELECT col1,col2
FROM
(
SELECT col1,col2,
CASE
WHEN LENGTH(RTRIM(TRANSLATE(ZIP , '*', ' 0123456789'))) = 0
THEN 0 ELSE 1
END as IsAllDigit
FROM S1234.PERSON
) AS Z
WHERE IsAllDigit=0
DB2 doesnot have regular expression facility like MySQL REGEXP
USE ISNUMERIC function;
ISUMERIC returns 1 if the parameter contains only numbers and zero if it not
EXAMPLE:
SELECT * FROM S1234.PERSON
WHERE ISNUMERIC(ZIP) = 1
Your statement doesn't validate against numbers but it says get everything that doesn't start with a space.
Let's suppose you ZIP code is a USA zip code, composed by 5 numbers.
db2 "with val as (
select *
from S1234.PERSON t
where xmlcast(xmlquery('fn:matches(\$ZIP,''^\d{5}$'')') as integer) = 1
)
select * from val"
For more information about xQuery:fn:matches: http://pic.dhe.ibm.com/infocenter/db2luw/v10r5/topic/com.ibm.db2.luw.xml.doc/doc/xqrfnmat.html
mySql does not have a native isNumberic() function. This would be pretty straight-forward in Excel with the ISNUMBER() function, or in T-SQL with ISNUMERIC(), but neither work in MySQL so after a little searching around I came across this solution...
SELECT * FROM S1234.PERSON
WHERE ZIP REGEXP ('[0-9]')
Effectively we're processing a regular expression on the contents of the 'ZIP' field, it may seem like using a sledgehammer to crack a nut and I've no idea how performance would differ from a more simple approach but it worked and I guess that's the point.
I have made more error-prone version based on the solution https://stackoverflow.com/a/36211270/565525, added intermedia result, some examples:
select
test_str
, TRIM(TRANSLATE(replace(trim(test_str), ' ', 'x'), 'yyyyyyyyyyy', '0123456789'))
, case when length(TRIM(TRANSLATE(replace(trim(test_str), ' ', 'x'), 'yyyyyyyyyyy', '0123456789')))=5 then '5-digit-zip' else 'not 5d-zip' end is_zip
from (VALUES
(' 123 ' )
,(' abc ' )
,(' a12 ' )
,(' 12 3 ')
,(' 99435 ')
,('99323' )
) AS X(test_str)
;
The result for this example set is:
TEST_STR 2 IS_ZIP
-------- -------- -----------
123 yyy not 5d-zip
abc abc not 5d-zip
a12 ayy not 5d-zip
12 3 yyxy not 5d-zip
99435 yyyyy 5-digit-zip
99323 yyyyy 5-digit-zip
Try checking if there's a difference between lower case and upper case. Numerics and special chars will look the same:
SELECT *
FROM S1234.PERSON
WHERE UPPER(ZIP COLLATE Latin1_General_CS_AI ) = LOWER(ZIP COLLATE Latin1_General_CS_AI)
Here's a working example for the case where you'd want to check zip codes in a range. You could use this code for inspiration to make a simple single post code check, if you want:
if local_test_environment?
# SQLite supports GLOB which is similar to LIKE (which it only has limited support for), for matching in strings.
where("(zip_code NOT GLOB '*[^0-9]*' AND zip_code <> '') AND (CAST(zip_code AS int) >= :range_start AND CAST(zip_code AS int) <= :range_finish)", range_start: range_start, range_finish: range_finish)
else
# SQLServer supports LIKE with more advanced matching in strings than what SQLite supports.
# SQLServer supports TRY_PARSE which is non-standard SQL, but fixes the error SQLServer gives with CAST, namely: Conversion failed when converting the nvarchar value 'US-19803' to data type int.
where("(zip_code NOT LIKE '%[^0-9]%' AND zip_code <> '') AND (TRY_PARSE(zip_code AS int) >= :range_start AND TRY_PARSE(zip_code AS int) <= :range_finish)", range_start: range_start, range_finish: range_finish)
end
Use regex.
SELECT * FROM S1234.PERSON
WHERE ZIP REGEXP '\d+'

SQL LIKE only one letter

When i use LIKE statement in my SQL,
for example,
SELECT * FROM table WHERE name = "%k"
It will return all rows, where name ends on k.
It can return : Ok, OOk, OOOk,
How i can do same statement but with one letter, so it returns only Ok.
Or 2 letters, so it returns only OOk?
_ is a single character wildcard.
SELECT * FROM table WHERE name = `_k`
See this IBM Reference
Use the equality operator (=) or the IN operator instead of the LIKE operator:
SELECT * FROM table WHERE name IN ('Ok', 'OOk')
Use the _ wildcard. It matches only a single character.
_k for Ok.
__k for Ook
depending on the length you provide
For 1 character 'X' followed by k
Select *
from table
where length(name) = 2
AND name = "%k"
For 2 character 'X' followed by k
Select *
from table
where length(name) = 3
AND name = "%k"
You should use an underscore (_) character. See the documentation about operator LIKE.
So, the query you need (1 or 2 chars before k) is:
SELECT * FROM table WHERE name LIKE '_k' OR name LIKE '__k'

Cheque Number problem

I have a column called check_num (bank check number) as VARCHAR2 type in a payment_line table(Oracle).
The requirement is "I have to search all those checks which numbers are greater than 12345.
Please suggest how can I achieve this?
There most likely is a more elegant solution, but this should do the trick:
SELECT *
FROM payment_line pl
WHERE LENGTH(TRIM(TRANSLATE(pl.check_num, '0123456789',' '))) IS NULL
AND TRIM(TRANSLATE(pl.check_num, '0123456789','0123456789')) > 12345;
edit:
If I understand your comment to Adam Paynter, for input of:
0A132
1A117
2A123
12D24
02134
11111
12345
21334
and you used 1A117 as your comparison the resulting set would be:
2A123
12D24
02134
11111
12345
21334
Can you confirm that both 02134 and 11111 should be in this result set? They dont seem to meet the requirements of > a value like 1A117. If, however, that was a typo, you can actually run a simple string comparison to get this set:
SELECT *
FROM payment_line pl
WHERE pl.check_num > '1A117';
edit 2
OK, I think I see where you are going with this. You are looking to get the rows in the db that have been entered after the input row. If you look at my formatted list above, you will see that your result set is everything below your input string. So, with that in mind, i submit for your approval the following:
SELECT *
FROM payment_line
WHERE rowid > (select rowid from payment_line where check_num ='1A117');
Unfortunately, Oracle does not provide a handy function such as IS_INTEGER(...), otherwise you could have done a query like:
-- Fictional, though desirable, query:
SELECT *
FROM checks
WHERE IS_INTEGER(check_num) AND TO_NUMBER(check_num) > 12345
However, there is a way to emulate such a function:
-- Real, though less-than-desirable, query:
SELECT *
FROM checks
WHERE TRIM(TRANSLATE(check_num, '0123456789', ' ')) IS NULL
AND TO_NUMBER(check_num) > 12345
The TRANSLATE(check_num, '0123456789', ' ') call replaces each digit within check_num with a space. For example:
check_num TRANSLATE(check_num, '0123456789', ' ')
---------------------------------------------------------------------
'12345' ' '
'cat' 'cat'
'123cat45' ' cat '
Therefore, if check_num contains only digits, then TRIM(TRANSLATE(check_num, '0123456789', ' ')) will be NULL (that is, the empty string).
I hope the following might help you -
select * from checkTable where TO_NUMBER(check_num) > 12345;
cheers
It's tricky to use to_number() in this requirement because forcing Oracle to apply a check that the value is safe to convert to a number before it applies the TO_NUMBER function is not so easy, and an ORA-01722 error might surface in the future.
I think that I would:
SELECT *
FROM payment_line pl
WHERE LENGTH(TRIM(TRANSLATE(pl.check_num, '0123456789',' '))) IS NULL
AND LPAD(pl.check_num,10,'0') > TO_CHAR(12345,'fm0000000000');
You might ask for the creation of an index on LPAD(pl.check_num,10,'0') to help with this.
If you're on 10g or later you can use regular expressions with an inline view.
The inner select is to get only the numeric check numbers. Then converting and using the where clause is easy. Something like
select * from (
select *
from payment_line
where regexp_like (check_num,'^[0-9]*$')
)
where to_number (check_num) > 12345;
Of course, this only works if you want all numeric check numbers greater than 12345. If you want "numbers" like 1A123 included as well, that's a different story.