how to get columns have long spaces ( multiple spaces) - sql

I have the below structure(' ' refers to empty spaces):
name description
---------------------
a yes
b ' '
c ' '
d null
I am searching for a query that give me the rows contain empty spaces, asked for the below result .
name description
---------------------
b ' '
c ' '
this query select * from tab1 where description =' '; will give me only c, in my query I have many values have long spaces.

You can user REGEXP_LIKE:
with src as (select 'a' as name,'yes' as description from dual
union all
select 'b',' ' from dual
union all
select 'c',' ' from dual
union all
select 'd',null from dual)
select * from src where regexp_like(description,'^[ ]+$'))
Edited: added regexp_like(description,'^[ ]+$') to take into account only descriptions with spaces. If there is a description in the format ' s ', ' s' or 's ' it will not be selected.

Use TRIM function to trim the spaces.
select * from tab1 where TRIM(description) IS NULL;
I have not tested it but it should work.

with this basic query:
with sample_data(name, description) as (
select 'a', 'yes' from dual union all
select 'b', ' ' from dual union all
select 'c', ' ' from dual union all
select 'd', null from dual
)
select *
from sample_data
you can pick and choose among the following where clauses to get your desired results:
where regexp_like(description,'[ ]')); -- at least one space in the string
where regexp_like(description,'[ ]{2,')); -- two or more consecutive spaces
where regexp_like(description,'^[ ]+$')); -- just spaces of any length
where regexp_like(description,'^[ ]{2,}')); -- just paces of length 2 or more
if you want any white space character (e.g. tabs, vertical tabs, non blanking spaces, etc.) you can replace the single space character class [ ] with this [[:space:]] named character class in any of the above where clauses.

Use LIKE operator
SELECT *
FROM tab1
WHERE description LIKE ' %'

Related

How to find values that contains only 0's and any other digit for example 000000001 or 0000010001 or 010101 or 0002 or 02020 or 0090 etc.?

I want to find 'default type values' in SQL that is entered when something like an ID number of company registration number is entered. Some of the values I see is a combination of 0's and another digit from 1-9. Examples I have seen is 00000001, 0000100, 000000002, 000001111, 0000090009, etc. The values vary in length also. Is there a way to find these values without hard coding? The value should contain at least one 0 and one or more of any other digit.
You want all strings that consist of only zero and one other digit. I.e. you want to find '0101', but not '0102'.
In order to do this, remove all zeros first. From the remaining string remove all digits equaling to its first character. This will result in an empty string or a string consisting of additional digits or characters. Only select those resulting in an empty string.
select *
from mytable
where replace(replace(value, '0', ''), substring(replace(value, '0', ''), 1, 1), '') = '';
Demo: https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=c307bbbf21ceeae619a966e995c3a567
You can use ISNUMERIC() function
SELECT ISNUMERIC(0000004);
This will return 1
SELECT ISNUMERIC('A');
This will return 0
So if you want to select all columns that are numeric only you can use this logic:
select *
from test
where ISNUMERIC(colA) = 1
Here is a small demo
Or you can use TRY_CAST() function:
select *
from test
where try_cast(colA as int) is not null
Alternative solution:
SELECT value
FROM mytable
CROSS JOIN (
SELECT '1' AS num
UNION ALL
SELECT '2'
UNION ALL
SELECT '3'
UNION ALL
SELECT '4'
UNION ALL
SELECT '5'
UNION ALL
SELECT '6'
UNION ALL
SELECT '7'
UNION ALL
SELECT '8'
UNION ALL
SELECT '9'
) n
WHERE REPLACE(REPLACE(value, '0', ''), num, '') = ''
AND REPLACE(value, '0', '') <> ''
AND value LIKE '%0%'

How can I do a replace with values from a table

This is my current code, what I want to do is rather than hard code this replace is put those values in a table and use those values to do the replace without a while or cursor. Keep in mind multiple replaces may happen to the same field for instance Mr. Guy would replace the "." but then would also need to replace "Mr ".
SELECT
REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(TRIM(di.FirstName), '.', ''), ',', ''), 'Mr ', ''), 'Dr ', ''), 'Mrs ', ''), 'Ms', '')
FROM core..asdf di
If your DBMS supports both GROUP_CONCAT() (or equivalent, like LISTAGG() in Vertica),
You can
create an in-line table with the titles you want to remove,
group-concatenate that in-line table into a single string, bar separated
surround that bar-separated list by rounded parentheses, and add '\b' for "word" boundary, '\.?' meaning zero or one times the dot character (and not any character), and '\s*' for one or more white spaces
and finally use that regular expression you just created on a REGEXP_REPLACE() call.
WITH
indata(fname) AS (
SELECT 'Mr Arthur'
UNION ALL SELECT 'Mrs Tricia'
UNION ALL SELECT 'Ms Eccentrica'
UNION ALL SELECT 'Dr Gag'
UNION ALL SELECT 'Mr. Arthur'
UNION ALL SELECT 'Mrs. Tricia'
UNION ALL SELECT 'Ms. Eccentrica'
UNION ALL SELECT 'Dr. Gag'
)
,
titles(title) AS (
SELECT 'Mr'
UNION ALL SELECT 'Mrs'
UNION ALL SELECT 'Ms'
UNION ALL SELECT 'Dr'
)
,
regx(regx) AS (
SELECT
'('||LISTAGG(title USING PARAMETERS separator='|')||')\b\.?\s*'
-- OR GROUP_CONCAT(title,',') in other DBMSs ...
FROM titles
)
-- control query ...
-- SELECT * FROM regx;
-- out regx
-- out ----------------------
-- out (Mr|Mrs|Ms|Dr)\.?\s*
SELECT
REGEXP_REPLACE(fname,regx) AS fname
FROM indata CROSS JOIN regx;
-- out fname
-- out ------------
-- out Arthur
-- out Tricia
-- out Eccentrica
-- out Gag
-- out Arthur
-- out Tricia
-- out Eccentrica
-- out Gag

how to fetch specific number of characters before the pattern

I have values like the below in my table:
SER : 3-576509910214, 4182 5979WM
I need to remove the white spaces first. then fetch the 8 numbers before or after the occurrence of matching string 'WM'. I need the output for the above value as '41825979'. I need to fetch 8 numbers after each occurrence of 'WM'.
WM can occur anywhere in the string.
How can I do that in with an Oracle SQL query?
This will return a string of digits up to 8 long from such a string:
select replace(regexp_substr(replace(str, ' ', ''), '[0-9]{1,8}WM'), 'WM', '')
If you want before and after, just modify the pattern:
select replace(regexp_substr(replace(str, ' ', ''), '[0-9]{1,8}WM|WM[0-9]{1-8}'), 'WM', '')
To take 8 digits before or after WM (after spaces are removed), use following:
WITH Demo(t) AS
(
SELECT 'SER : 3-576509910214, 4182 5979WM' FROM dual
UNION ALL
SELECT 'SER : 3-576509910214, 4182 5 979 WM' FROM dual
UNION ALL
SELECT 'SER : 3-576509910214,WM 4182 5979' FROM dual
)
SELECT
REPLACE(COALESCE(
REGEXP_SUBSTR(REPLACE(t, ' ', ''), '[0-9]{8}WM'),
REGEXP_SUBSTR(REPLACE(t, ' ', ''), 'WM[0-9]{8}')
), 'WM', '')
FROM Demo

SQL to find upper case words from a column

I have a description column in my table and its values are:
This is a EXAMPLE
This is a TEST
This is a VALUE
I want to display only EXAMPLE, TEST, and VALUE from the description column.
How do I achieve this?
This could be a way:
-- a test case
with test(id, str) as (
select 1, 'This is a EXAMPLE' from dual union all
select 2, 'This is a TEST' from dual union all
select 3, 'This is a VALUE' from dual union all
select 4, 'This IS aN EXAMPLE' from dual
)
-- concatenate the resulting words
select id, listagg(str, ' ') within group (order by pos)
from (
-- tokenize the strings by using the space as a word separator
SELECT id,
trim(regexp_substr(str, '[^ ]+', 1, level)) str,
level as pos
FROM test t
CONNECT BY instr(str, ' ', 1, level - 1) > 0
and prior id = id
and prior sys_guid() is not null
)
-- only get the uppercase words
where regexp_like(str, '^[A-Z]+$')
group by id
The idea is to tokenize every string, then cut off the words that are not made by upper case characters and then concatenate the remaining words.
The result:
1 EXAMPLE
2 TEST
3 VALUE
4 IS EXAMPLE
If you need to handle some other character as an upper case letter, you may edit the where condition to filter for the matching words; for example, with '_':
with test(id, str) as (
select 1, 'This is a EXAMPLE' from dual union all
select 2, 'This is a TEST' from dual union all
select 3, 'This is a VALUE' from dual union all
select 4, 'This IS aN EXAMPLE' from dual union all
select 5, 'This IS AN_EXAMPLE' from dual
)
select id, listagg(str, ' ') within group (order by pos)
from (
SELECT id,
trim(regexp_substr(str, '[^ ]+', 1, level)) str,
level as pos
FROM test t
CONNECT BY instr(str, ' ', 1, level - 1) > 0
and prior id = id
and prior sys_guid() is not null
)
where regexp_like(str, '^[A-Z_]+$')
group by id
gives:
1 EXAMPLE
2 TEST
3 VALUE
4 IS EXAMPLE
5 IS AN_EXAMPLE
Here's another solution. It was inspired by Aleksej's answer.
The idea? Get all the words. Then aggregate only fully uppercased to a list.
Sample data:
create table descriptions (ID int, Description varchar2(100));
insert into descriptions (ID, Description)
select 1 as ID, 'foo Foo FOO bar Bar BAR' as Description from dual
union all select 2, 'This is an EXAMPLE TEST Description VALUE' from dual
;
Query:
select id, Description, listagg(word, ',') within group (order by pos) as UpperCaseWords
from (
select
id, Description,
trim(regexp_substr(Description, '\w+', 1, level)) as word,
level as pos
from descriptions t
connect by regexp_instr(Description, '\s+', 1, level - 1) > 0
and prior id = id
and prior sys_guid() is not null
)
where word = upper(word)
group by id, Description
Result:
ID | DESCRIPTION | UPPERCASEWORDS
-- | ----------------------------------------- | ------------------
1 | foo Foo FOO bar Bar BAR | FOO,BAR
2 | This is an EXAMPLE TEST Description VALUE | EXAMPLE,TEST,VALUE
It is possible to achieve this thanks to the REGEXP_REPLACE function:
SELECT REGEXP_REPLACE(my_column, '(^[A-Z]| |[a-z][A-Z]*|[A-Z]*[a-z])', '') AS Result FROM my_table
It uses a regex which replaces first upper case char of the line and converts every lower case char and space with blanks.
Try this:
SELECT SUBSTR(column_name, INSTR(column_name,' ',-1) + 1)
FROM your_table;
This should do the trick:
SELECT SUBSTR(REGEXP_REPLACE(' ' || REGEXP_REPLACE(description, '(^[A-Z]|[a-z]|[A-Z][a-z]+|[,])', ''), ' +', ' '), 2, 9999) AS only_upper
FROM (
select 'Hey IF you do not know IT, This IS a test of UPPERCASE and IT, with good WILL and faith, Should BE fine to be SHOWN' description
from dual
)
I have added condition to strip commas, you can add inside that brakets other special characters to remove.
ONLY_UPPER
-----------------------------------
IF IT IS UPPERCASE IT WILL BE SHOWN
This is a function based on some of the regular expression answers.
create or replace function capwords(orig_string varchar2)
return varchar2
as
out_string varchar2(80);
begin
out_string := REGEXP_REPLACE(orig_string, '([a-z][A-Z_]*|[A-Z_]*[a-z])', '');
out_string := REGEXP_REPLACE(trim(out_string), '( *)', ' ');
return out_string;
end;
/
Removes strings of upper case letters and underscores that have lower case letters
on either end. Replaces multiple adjacent spaces with one space.
Trims extra spaces off of the ends. Assumes max size of 80 characters.
Slightly edited output:
>select id,str,capwords(str) from test;
ID STR CAPWORDS(STR)
---------- ------------------------------ ------------------
1 This is a EXAMPLE EXAMPLE
2 This is a TEST TEST
3 This is a VALUE VALUE
4 This IS aN EXAMPLE IS EXAMPLE
5 This is WITH_UNDERSCORE WITH_UNDERSCORE
6 ThiS IS aN EXAMPLE IS EXAMPLE
7 thiS IS aN EXAMPLE IS EXAMPLE
8 This IS wiTH_UNDERSCORE IS
If you only need to "display" the result without changing the values in the column then you can use CASE WHEN (in the example Description is the column name):
Select CASE WHEN Description like '%EXAMPLE%' then 'EXAMPLE' WHEN Description like '%TEST%' then 'TEST' WHEN Description like '%VALUE%' then 'VALUE' END From [yourTable]
The conditions are not case sensitive even if you write it all in uppercase.
You can add Else '<Value if all conditions are wrong>' before the END in case there are descriptions that don't contain any of the values. The example will return NULL for those cases, and writing ELSE Description will return the original value of that row.
It also works if you need to update. It is simple and practical, easy way out, haha.

case statement to delete extra spaces only when there is some

I replace all blanks with # using this
SELECT *, REPLACE(NAME,' ','#') AS NAME2
which results miss#test#blogs############## (different number of #s dependent on length of name!
I then delete all # signs after the name using this
select *, substring(Name2,0,charindex('##',Name2)) as name3
which then gives my desired results of, for example MISS#test#blogs
However some wheren't giving this result, they are null. This is because annoyingly some rows in the sheet I have read in dont have the spaces after the name.
is there a case statement i can use so it only deletes # signs after the name if they are there in the first place?
Thanks
The function rtrim can be used to remove trailing spaces. For example:
select replace(rtrim('miss test blogs '),' ','#')
-->
'miss#test#blogs'
Example at SQL Fiddle.
try this:
Declare #t table (name varchar(100),title varchar(100),forename varchar(100))
insert into #t
values('a b c','dasdh dsalkdk asdhl','asd dfg sd')
SELECT REPLACE(REPLACE(REPLACE(LTRIM(RTRIM(name)),' ',' '+CHAR(7)),CHAR(7)+' ','') ,CHAR(7),'') AS Name,
REPLACE(REPLACE(REPLACE(LTRIM(RTRIM(title)),' ',' '+CHAR(7)),CHAR(7)+' ','') ,CHAR(7),'') AS title,
REPLACE(REPLACE(REPLACE(LTRIM(RTRIM(forename)),' ',' '+CHAR(7)),CHAR(7)+' ','') ,CHAR(7),'') AS forename
FROM #t WHERE
(CHARINDEX(' ',NAME) > 0 or CHARINDEX(' ',title) > 0 or CHARINDEX(' ',forename) > 0)
SQL Fiddle Demo
select name2, left(name2,len(name2)+1-patindex('%[^#]%',reverse(name2)+'.'))
from (
SELECT *, REPLACE(NAME,' ','#') AS NAME2
from t
) x;
Check this SQL Fiddle
For posterity, sample table:
create table t (name varchar(100));
insert t select 'name#name#ne###'
union all select '#name#name'
union all select 'name name hi '
union all select 'joe public'
union all select ''
union all select 'joe'
union all select 'joe '
union all select null
union all select ' leading spaces'
union all select ' leading trailing ';
Don't quite understand the question, but if the problem is there is not spaces after some names, can't you do this first:
SELECT *, REPLACE(NAME+' ',' ','#') AS NAME2
i.e., add a space to all names right off the bat?
I had this same problem some days ago.
Well actually, there's a quickly way to subtract the spaces from both the begin and end inside strings. In SQL Server, you can use the RTRIM and LTRIM for this. The first one supresses spaces from right side and the second supresses from left. But, if in your scenario also may exists more than one space in the middle of the string I sugest you take a look on this post on SQL Server Central: http://www.sqlservercentral.com/articles/T-SQL/68378/
There the script's author explain, in details, a good solution for this situation.