Repetitions in field in Firebird without regex - sql

I'm trying to craft a query which rejects a row when some field is all the same characters. Ie. I want to select people named Smith but not people named aaaaaa or bbbb.
I can't use regexes, as Firebird's SIMILAR TO doesn't have backreferences.
How would you do it?

Meh, this is not what I wanted, but this will do. It works on aaaaaa, but wouldn't on abbbbbb.
SELECT *
FROM PEOPLE
WHERE replace(upper(NAME), substring(upper(NAME) FROM 1 FOR 1), '') = ''

Related

SQL Server LIKE caret (^) for NOT does not work as expected

I was reading the article at mssqltips and wanted to try the caret in regex. I understand regex pretty well and use it often, although not much in SQl Server queries.
For the following list of names, I had thought that 1) select * from people where name like '%[^m]%;' will return those names that do not contain 'm'. But it doesn't work like that. I know I can do 2) select * from people where name not like '%m%'; to get the result I want, but I'm just baffled why 1) doesn't work as expected.
Amy
Jasper
Jim
Kathleen
Marco
Mike
Mitchell
I am using SQL Server 2017, but here is a fiddle:
sql fiddle
'%[^m]%' would be true for any string containing a character that is not m. An expanded version would be '%[Any character not m]%'. Since all of those strings contain a character other than m, they are valid results.
If you had a string like mmm, where name like '%[^m]%' would not return that row.

Combine two columns and perform a where operation on the result

I have two columns, one for 'firstName' and one for 'lastName'. I'm trying to perform a where operation on the concatenation of those two columns to match for a full name.
Here is what I've tried:
select * from table where concat_ws(' ', 'firstName', 'lastName') like '%some_value%'
This just returns a blank array.
Example Data:
firstName
lastName
Clayton
Smith
Barbara
Clayman
Sam
Peterson
when some_value = Clay, it should return 'Clayton Smith' and 'Barbara Clayman'
I got a lot of this syntax from some other stackoverflow answers which were marked as solutions to a similar problem, however when implementing this myself I couldn't get it to work.
FWIW I'm going to be building these queries with knex.js so if there's a knex.js specific solution feel free to answer with that.
The arguments to your CONCAT_WS call should be in double quotes. If they're in single quotes, Postgres will interpret them as string literals. This should work:
SELECT * FROM table WHERE CONCAT_WS(' ', "firstName", "lastName") ILIKE '%some_value%'
I also recommend using ILIKE rather than LIKE - this will make the pattern matching for your search term be case insensitve.
use STR_POS
The PostgreSQL strpos() function is used to find the position, from where the substring is being matched within the string.
https://w3resource.com/PostgreSQL/strpos-function.php#:~:text=The%20PostgreSQL%20strpos()%20function,being%20matched%20within%20the%20string.&text=Example%20of%20PostgreSQL%20STRPOS(),within%20the%20argument%20is%205.
select * from table where strpos(concat_ws(' ', first_name, last_name),'Clay') > 0
Replace literal with variable

SELECT middle part of a String if it exists. Postgresql

i've got a problem with transferring "real-World" data into my schema.
It's actually a "project" for my Database course and they gave us ab table with dog race results. This Table has a column which contains the name of the Dog (which itself consists of the actuall name and the name of the breeder) and informations about the Birthcountry, actual living Country and the birth year.
Example filed are "Lillycette [AU 2012]" or "Black Bear Lee [AU/AU 2013]" or "Lemon Ralph [IE/UK 1998]".
I've managed it to get out the first word and save it in the right column with split_part like this:
INSERT INTO tblHund (rufname)
SELECT
split_part(name, ' ', 1) AS rufname,
FROM tblimport;
tblimport is a table where I dumped the data from the csv file.
That works just as it should.
Accessing the second part of the Name with this fails because sometimes there isn't a second part and sometimes times there second part consists of two words.
And this is the where iam stuck right now.
I tried it with substring and regular expressions:
INSERT INTO tblZwinger (Name)
SELECT
substring(vatertier from E'[^ ]*\\ ( +)$')AS Name
FROM tblimport
WHERE substring(vatertier from E'[^ ]*\\ ( +)$') != '';
The above code is executed without errors but actually does nothing because the SELECT statement just give empty strings back.
It took me more then 3h to understand a bit of this regular Expressions but I still feel pretty stupid when I look at them.
Is there any other way of doing this. If so just give me a hint.
If not what is wrong with my expression above?
Thanks for your help.
You need to use atom ., which matches any single character inside capturing group:
E'[^ ]*\\ (.+)$'
SELECT
tblimport.*,
ti.parts[1] as f1,
ti.parts[2] as f2, -- It should be the "middle part"
ti.parts[3] as f3
FROM
tblimport,
regexp_matches(tblimport.vatertier, '([^\s]+)\s*(.*)\s+\[(.*)\]') as ti(parts)
WHERE
nullif(ti.parts[2], '') is not null
Something like above.

Matching exactly 2 characters in string - SQL

How can i query a column with Names of people to get only the names those contain exactly 2 “a” ?
I am familiar with % symbol that's used with LIKE but that finds all names even with 1 a , when i write %a , but i need to find only those have exactly 2 characters.
Please explain - Thanks in advance
Table Name: "People"
Column Names: "Names, Age, Gender"
Assuming you're asking for two a characters search for a string with two a's but not with three.
select *
from people
where names like '%a%a%'
and name not like '%a%a%a%'
Use '_a'. '_' is a single character wildcard where '%' matches 0 or more characters.
If you need more advanced matches, use regular expressions, using REGEXP_LIKE. See Using Regular Expressions With Oracle Database.
And of course you can use other tricks as well. For instance, you can compare the length of the string with the length of the same string but with 'a's removed from it. If the difference is 2 then the string contained two 'a's. But as you can see things get ugly real soon, since length returns 'null' when a string is empty, so you have to make an exception for that, if you want to check for names that are exactly 'aa'.
select * from People
where
length(Names) - 2 = nvl(length(replace(Names, 'a', '')), 0)
Another solution is to replace everything that is not an a with nothing and check if the resulting String is exactly two characters long:
select names
from people
where length(regexp_replace(names, '[^a]', '')) = 2;
This can also be extended to deal with uppercase As:
select names
from people
where length(regexp_replace(names, '[^aA]', '')) = 2;
SQLFiddle example: http://sqlfiddle.com/#!4/09bc6
select * from People where names like '__'; also ll work

Ignoring spaces between words - an SQL question

I want to grab from a db a record with name='John Doe'.
I'd like my query to also grab 'John(4 spaces between)Doe','John(2 spaces betwewen)Doe' etc. (at least one space however).
I'd also like that the case won't matter, so I can also get 'John Doe' by typing
'john doe' etc.
Try this:
SELECT * FROM table WHERE lower(NAME) like 'john%doe%'
use like with wildcards (e.g. %) to get around the spaces and the lower (orlcase) to be case insensitive.
EDIT:
As the commenters pointed out, there are two shortcomings within this solution.
First: you will select "johnny doe" or worse "john Eldoe", or worse, "john Macadoelt" with this query, so you'll need extra filtering on the application side.
Second: using a function can lead to table scans instead of index scans. This may be avoided, if your dbms supports function based indexes. See this Oracle example
If your database has Replace function
Select * From Table
Where Upper(Replace(name, ' ', '')) = 'JOHNDOE'
The rest of these will return rows where the middle part between John and Doe is anything, not just spaces...
if your database has left function and Reverse, Try either
Select * From Table
Where left(Upper(name), 4) = 'JOHN'
And Left(Reverse(Upper(name), 3)) = 'EOD'
else use substring and reverse
Select * From Table
Where substring(Upper(name), 4) = 'JOHN'
And substring(Reverse(Upper(name), 3)) = 'EOD'
or Like operator
Select * From Table
Where Upper(name) Like 'JOHN%DOE'
In MYSQL:
select user_name from users where lower(trim(user_name)) regexp 'john[[:blank:]]+doe' = 1;
Explanation:
In the above case the user_name matches the regular expression john(one or more spaces)doe. The comparison is case insensitive and trim takes care of spaces before and after the string.
In case the search string contains special characters, they need to be escaped. More in mysql documentation: http://dev.mysql.com/doc/refman/5.5/en/regexp.html
In sql you can use wildcards, that is a character that stands in place of other characters. for example:
select * from table where name like 'john%doe'
will select all names that start with john and end with doe no matter how many characters in between.
This article explains more and gives some options.
The wildcard will match on zero characters, so if you want at least one space then you should do
select * from table where lower(name) like 'john %doe'
In Oracle you can do:
SELECT * FROM table
WHERE UPPER(REGEXP_REPLACE(NAME,'( ){2,}', ' ') = 'JOHN DOE';
No false positives like 'john mordoe' etc.