sql query about string function - sql

ID MOBILE
1 9869600733
2 9869600793
3 9869600799
all id whose mobile number containing 9 three times(using string functions like replace, substr, etc)... ? (without like , % , etc)

You can use LEN and Replace
Where len(MOBILE)-len(replace(MOBILE ,'9',''))>=3
Note : Some DBMS uses LENGTH instead of LEN
Where length(MOBILE)-length(replace(MOBILE ,'9',''))>=3
DEMO
replace(MOBILE ,'9','') will replace all the 9's with empty
string
length(MOBILE) will count the number of characters in Mobile
column
length(replace(MOBILE ,'9','')) will count the number of characters
in Mobile column as replacing 9's with empty string
length(MOBILE)-length(replace(MOBILE ,'9','')) here the
difference will tell the number of missing characters that is our 9, you can use this difference to count the 9

exactly three '9's:
Select * from mytable
Where len(mobile) - len(replace(mobile, '9', '')) = 3
at least three '9's:
Select * from mytable
Where len(mobile) - len(replace(mobile, '9', '')) >= 3

Related

How does select SUBSTRING('uppercase ', LEN('uppercase')-2, 3) result in "ase"

Please see below query:
select SUBSTRING('uppercase ', LEN('uppercase')-2, 3)
Can someone explain how it is working and giving output as ase
Please help.
SUBSTRING function extracts characters from a string. In additon,LEN function provide the length of string. the LEN('uppercase') would be 9.
SUBSTRING(string, start, length)
your query is like
select SUBSTRING('uppercase ', LEN('uppercase')-2, 3)---equivalent
select SUBSTRING('uppercase ', 9-2, 3) --equivalent
select SUBSTRING('uppercase ', 7, 3)
hence it provide ase
Should be:
select SUBSTRING('uppercase ', LENGTH('uppercase')-2, 3) // Mysql hasn't len function
LENGTH('uppercase') // return 9, the length of string.
SUBSTRING('uppercase ', 9-2, 3) // return a substring from the index of 7 and three characters, that is ase
Go through the documentation of substring function
SUBSTRING ( expression ,start , length )
expression
Is a character, binary, text, ntext, or image expression.
start
Is an integer or bigint expression that specifies where the
returned characters start. (The numbering is 1 based, meaning that the
first character in the expression is 1). If start is less than 1, the
returned expression will begin at the first character that is
specified in expression. In this case, the number of characters that
are returned is the largest value of either the sum of start + length-
1 or 0. If start is greater than the number of characters in the value
expression, a zero-length expression is returned.
length
Is a positive integer or bigint expression that specifies how
many characters of the expression will be returned. If length is
negative, an error is generated and the statement is terminated. If
the sum of start and length is greater than the number of characters
in expression, the whole value expression beginning at start is
returned.
In your case,
SUBSTRING('uppercase ', LEN('uppercase')-2, 3)
SUBSTRING('uppercase ', 9-2, 3)
SUBSTRING('uppercase ', 7, 3)
u p p e r c a s e
1 2 3 4 5 6 7 8 9
<====> (From 7 pick 3 characters)
a s e

how to repeat characters in a string

I'm trying to link two tables, one has an 'EntityRef' that's made of four alpha characters and a sequential number...
EntityRef
=========
SWIT1
LIVE32
KIRB48
MEHM38
BRAD192
The table that I'm trying to link to stores the reference in a 15 character field where the 4 alphas are at the start and the numbers are at the end but with zeros in between to make up the 15 characters...
EntityRef
=========
SWIT00000000001
LIVE00000000032
So, to get theses to link, my options are to either remove the zeros on one field or add the zeros on the other.
I've gone for the later as it seems to be a simpler approach and eliminates the risk of getting into problems if the numeric element contains a zero.
So, the alpha is always 4 characters at the beginning and the number is the remainder and 15 minus the LEN() of the EntityRef is the number of zeros that I need to insert...
left(entityref,4) as 'Alpha',
right(entityref,len(EntityRef)-4) as 'Numeric',
15-len(EntityRef) as 'No.of Zeros'
Alpha Numeric No.of Zeros
===== ======= ===========
SWIT 1 10
LIVE 32 9
KIRB 48 9
MEHM 38 9
MALL 36 9
So, I need to concatenate the three elements but I don't know how to create the string of zeros to the specified length...how do I do that??
Concat(Alpha, '0'*[No. of Zeros], Numeric)
What is the correct way to repeat a character a specified number of times?
You can use string manipulation. In this case:
LEFT() to get the alpha portion.
REPLICATE() to get the zeros.
STUFF() to get the number.
The query:
select left(val, 4) + replicate('0', 15 - len(val)) + stuff(val, 1, 4, '')
from (values ('SWIT1'), ('ABC12345')) v(val)
You may try left padding with zeroes:
SELECT
LEFT(EntityRef, 4) +
RIGHT('00000000000' + SUBSTRING(ISNULL(EntityRef,''), 5, 30), 11) AS EntityRef
FROM yourTable;
Demo
With casting to integer the numeric part:
select *
from t1 inner join t2
on concat(left(t2.EntityRef, 4), cast(right(t2.EntityRef, 11) as bigint)) = t1.EntityRef
See the demo.
I found the answer as soon as I posted the question (sometimes it helps you think it through!).
(left(entityref,4) + replicate('0',15-len(EntityRef)) +
right(entityref,len(EntityRef)-4)),

SQL Plus show first four and last 4 numbers in the output

How can I select a columns first 4 digits and last 4 digits and use an "X" placement for all the numbers in between?
Example
SELECT id from users where user_name ='Tom';
Output
5958694850384567
I am trying to get only the first and last 4 numbers with x's as placements to any number that is being masked:
Trying to get it to look like
Output:5958XXXXXXXX4567
Here is my query so far:
SELECT SUBSTR(id, 1, 4) from users
where user_name ='Tom'
Thank you for your time!
Have you considered simply use the LEFT() and RIGHT() functions? These will give you a specific number of characters from the left or right of a given string respectively.
You can also combine those to build your complete string using the CONCAT() function:
SELECT CONCAT(LEFT(id, 4), 'XXXXXXXX', RIGHT(id, 4))
FROM users
WHERE user_name = 'Tom'
Additionally, if you don't always have a given number of characters within the string, you could calculate the middle section of your output as well via the REPLICATE() function and a bit of math:
SELECT CONCAT(LEFT(id, 4), REPLICATE('X', LEN(id) - 8), RIGHT(id, 4))
FROM users
WHERE user_name = 'Tom'
Oracle Version
I didn't realize that you were using Oracle specifically and assumed SQL Server, so I'll provide some similar code to handle this in that flavor:
SELECT LEFT(id, 4) || RPAD('X', LEN(id) - 8, 'X') || RIGHT(id, 4)
FROM users
WHERE user_name = 'Tom'

In SQL how to select tuples whose "character varying(5)" column values are fixed size?

For example I have this table with a zipcode column(zipcode character varying(5)) but some of "bad" rows have invalid zipcode like "9000" or "2". and I want all the tuples whose zipcode values have exactly 5 characters.
How to translate
SELECT * FROM mytable WHERE zipcode "is size 5"
to SQL?
I am using postgresql btw.
SELECT * FROM mytable WHERE zipcode like "_____"
(Five underscores)
OR
SELECT * FROM mytable WHERE LENGTH(Trim(zipcode)) = 5
LENGTH function in postgresql
Imagine that you've data like below
zipcode
-------
5
5
900 5
900 2
900
90025
68656
so you need to use trim() function else no need to use trim(), just char_length(zipcode)=5; or length(zipcode)=5; is enough.
SELECT *
FROM zips
WHERE length(trim(zipcode)) =5
or
SELECT *
FROM zips
WHERE char_length(trim(zipcode))=5
trim(string):- Remove the longest string containing only the characters (a
space by default)
from the start/end/both ends of the string
length(string):- returns the length of the string measured in bytes.
char_length(string) or character_length(string):- returns the length of the string measured in
characters.

SQL change date formats inside a string

I would like to convert a string containing dates in SQL select from Oracle 11g database.
Original string (CLOB) example:
"1.12.2011 - event 1
2.2.2012 - event 2
13.3.2012 - event 44"
Desired output:
"20111201 - event 1
20120202 - event 2
20120313 - event 44"
Is there a better (faster) way than using 4 separate replacements?
regexp_replace(regexp_replace(regexp_replace(regexp_replace(my_string,
'(\d\d)\.(\d\d)\.(20\d\d)', '\3\2\1'),
'(\d\d)\.(\d)\.(20\d\d)', '\30\2\1'),
'(\d)\.(\d\d)\.(20\d\d)', '\3\20\1'),
'(\d)\.(\d)\.(20\d\d)', '\30\20\1')
Especially if you're using clobs you have to be careful unless you're certain of the data in there.
However, if your clob only looks like that then you need threeregexp_replace in order for this to work; it'll also be much more dynamic. Just explicitly specify digits using [[:digit:]] then specify a minimum and maximum number of times these digits could be there using {1,2}.
Then the following would work:
select regexp_replace(
regexp_replace(
regexp_replace( my_string
, '([[:digit:]]{1,2})\.([[:digit:]]{1,2})\.(20[[:digit:]]{2})'
, '\3-\2-\1')
, '-([[:digit:]]{1}(-|$))'
, '0\1' )
, ('-')
, '')
from dual
This means:
match ( group 1 ) 1 or 2 digits
match a full stop.
match ( group 2 ) 1 or 2 digits
match a full stop
match ( group 3 ) 20 + 2 digits.
Then take out only groups 1, 2 and 3, i.e. ignoring the full stops and return then in the order 3, 2, 1 padded with a hyphen
Then replace any [digit] that is followed by either a hyphen or the end of the string, i.e. the number of digits is only 1 with -0[digit].
Lastly replace all the hyphens.
Separately from that I agree with tbone. It would make a lot more sense to store this data in a separate table (event_id number, event_date date). Any string transformations are easy with no chance of getting it wrong, unlike in this situation, and the data is easy to query and compare.
there are no better options (both correct and readable) with better performance - or if there are, no one cares..
i prefer a 2-level regexp_replace for date part:
select regexp_replace(
regexp_replace( my_string,
'([[:digit:]]{1,2})\.([[:digit:]]{1,2})\.(20[[:digit:]]{2})',
'\3-0\2-0\1' ),
'(20[[:digit:]]{2})-0?([[:digit:]]{2})-0?([[:digit:]]{2})',
'\3\2\1' )
from dual;
Demo
Maybe try doing:
select to_char(to_date('13.3.2011', 'DD.MM.YYYY'),'YYYYMMDD') from dual;