Check if character column contains numeric value in DB/2 with sql - sql

We have an AS400 that the db/2 is stored on and I am trying to join a table where character column contains the value of a numeric column.
I am running this in visual studio and I tried cast(val as char) and receive a 'as' not recognized, I tried CONVERT, and that isn't recognized either. Here is my original query:
SELECT *
FROM tab e, tab n
WHERE (e.LN = 0001) AND (n.RMK LIKE '%' + e.ORDNO)
n.RMK contains a character value which is consistent but something like, "ordr 1401" and then e.ORDNO contains a numeric value which would be 1401
I want to see if e.RMK contains the 1401 value in e.ORDNO.
When I run that query I get a Errot type 6 = Numeric data that is not valid error. So I figure I would try and convert the numeric value to char and try again.
Like so,
SELECT *
FROM tab e, tab n
WHERE (e.LN = 0001) AND n.RMK LIKE '%' + cast(e.ORDNO as varchar(10))
This did not work,
I also tried
n.RMK LIKE '%' + CONVERT(VARCHAR(10), e.ORDNO) and I get CONVERT not recognized.

First off, best practice is to use explicit joins.
Secondly, CAST (fld AS CHAR) should work, though it defaults to CHAR(1). You probably need more than that.
Third, assuming the prefix is always "ordr " I'd use a SUBSTR()
SELECT *
FROM tab e
JOIN tab n ON n.rmk = INT(SUBSTR(e.ordno,6))
WHERE e.ln = 1

Finally got a working solution although it may not be the best:
SELECT *
FROM tab e, tab n
WHERE (e.LN = 0001) AND (n.RMK LIKE CONCAT(RTRIM(CONCAT('%', CHAR(e.ORDNO))), '%'))
There was whitespace being added to the end of the e.ORDNO string for some reason using CHAR and there was whitespace at the end of the RMK string too; and the wildcard search wouldn't work unless I prepended and appended the '%' to e.ORDNO or I did a right trim on both n.RMK and e.ordno. Not sure if one way is better than the other.

Related

Full Text Search Using Multiple Partial Words

I have a sql server database that has medical descriptions in it. I've created a full text index on it, but I'm still figuring out how this works.
The easiest example to give is if there is a description of Hypertensive heart disease
Now they would like to be able to type hyp hea as a search term and have it return that.
So from what I've read it seems like my query needs to be something like
DECLARE #Term VARCHAR(100)
SET #Term = 'NEAR(''Hyper*'',''hea*'')'
SELECT * FROM Icd10Codes WHERE CONTAINS(Description, #Term)
If I take the wild card out for Hypertensive and heart, and type out the full words it works, but adding the wild card in returns nothing.
If it makes any difference I'm using Sql Server 2017
So it was a weird syntax issue that didn't cause an error, but stopped the search from working.
I changed it to
SELECT * FROM Icd10Codes where CONTAINS(description, '"hyper*" NEAR "hea*"')
The key here being I needed double quotes " and not to single quotes. I assumed it was two single quotes, the first to escape the second, but it was actually double quotes. The above query returns the results exactly as expected.
this will work:
SELECT * FROM Icd10Codes where SOUNDEX(description)=soundex('Hyp');
SELECT * FROM Icd10Codes where DIFFERENCE(description,'hyp hea')>=2;
You could try a like statement. You can find a thorough explanation here.
Like so:
SELECT * FROM Icd10Codes WHERE Icd10Codes LIKE '%hyp hea%';
And then instead of putting the String in there just use a variable.
If you need to search for separated partial words, as in an array of search terms, it gets a bit tricky, since you need to dynamically build the SQL statement.
MSSQL provides a few features for full text search. You can find those here. One of them is the CONTAINS keyword:
SELECT column FROM table WHERE CONTAINS (column , 'string1 string2 string3');
For me - this had more mileage.
create a calculated row with fields as full text search.
fullname / company / lastname all searchable.
ALTER TABLE profiles ADD COLUMN fts tsvector generated always as (to_tsvector('english', coalesce(profiles.company, '') || ' ' || coalesce(profiles.broker, '') || ' ' || coalesce(profiles.firstname, '') || ' ' || coalesce(profiles.lastname, '') || ' ' )) stored;
let { data, error } = await supabase.from('profiles')
.select()
.textSearch('fts',str)

SQL finding rows that only contain chars from a certain Unicode range

I recently asked a question to obtain rows that contain characters in a certain Unicode range.
SELECT *
FROM #kanjinames
WHERE UNICODE(LEFT(ForeNames, 1)) BETWEEN 0x4e00 AND 0x9fff
A very helpful user shared the above with me. To my understanding it checks the first character on the left and if it is within the Unicode range it returns an a the row. Through testing I believe this works.
My current problem is how do I go about checking the entire column is within the range? For example:
石山コンタクトレンズ
The above contains characters outside of the range (the first two characters are within range) in the query above but I am not sure about how I go about checking the entire field. I am away of using stuff like
is not like N'%^a-z%'
for the English alphabet. Just not sure how to apply it for this situation.
Any help would be great on this.
I think this will work:
SELECT *
FROM #kanjinames
WHERE ForeNames NOT LIKE '%[^' + NCHAR(0x4e00) + '-' NCHAR(0x9fff) + ']%';
That is, the string contains no characters outside that sequence.
Edit: I had to alter this slightly to get it to work. I had to use the decimal values instead of the hex.
SELECT *
FROM #kanjinames
WHERE ForeNames NOT LIKE '%[^' + NCHAR(19968) + '-' + NCHAR(40802) + ']%';
This still returns blank values but I removed those separately.

Get rows that contain only certain characters

I want to get only those rows that contain ONLY certain characters in a column.
Let's say the column name is DATA.
I want to get all rows where in DATA are ONLY (must have all three conditions!):
Numeric characters (1 2 3 4 5 6 7 8 9 0)
Dash (-)
Comma (,)
For instance:
Value "10,20,20-30,30" IS OK
Value "10,20A,20-30,30Z" IS NOT OK
Value "30" IS NOT OK
Value "AAAA" IS NOT OK
Value "30-" IS NOT OK
Value "30," IS NOT OK
Value "-," IS NOT OK
Try patindex:
select * from(
select '10,20,20-30,30' txt union
select '10,20,20-30,40' txt union
select '10,20A,20-30,30Z' txt
)x
where patindex('%[^0-9,-]%', txt)=0
For you table, try like:
select
DATA
from
YourTable
where
patindex('%[^0-9,-]%', DATA)=0
As per your new edited question, the query should be like:
select
DATA
from
YourTable
where
PATINDEX('%[^0-9,-]%', DATA)=0 and
PATINDEX('%[0-9]%', LEFT(DATA, 1))=1 and
PATINDEX('%[0-9]%', RIGHT(DATA, 1))=1 and
PATINDEX('%[,-][-,]%', DATA)=0
Edit: Your question was edited, so this answer is no longer correct. I won't bother updating it since someone else already has updated theirs. This answer does not fulfil the condition that all three character types must be found.
You can use a LIKE expression for this, although it's slightly convoluted:
where data not like '%[^0123456789,!-]%' escape '!'
Explanation:
[^...] matches any character that is not in the ... part. % matches any number (including zero) of any character. So [^0123456789-,] is the set of characters that you want to disallow.
However: - is a special character inside of [], so we must escape it, which we do by using an escape character, and I've chosen !.
So, you match rows that do not contain (not like) any character that is not in your disallowed set.
Use option with PATINDEX and LIKE logic operator
SELECT *
FROM dbo.test70
WHERE PATINDEX('%[A-Z]%', DATA) = 0
AND PATINDEX('%[0-9]%', DATA) > 0
AND DATA LIKE '%-%'
AND DATA LIKE '%,%'
Demo on SQLFiddle
As already mentioned u can use a LIKE expression but it will only work with some minor modifications, otherwise too many rows will be filtered out.
SELECT * FROM X WHERE T NOT LIKE '%[^0-9!-,]%' ESCAPE '!'
see working example here:
http://sqlfiddle.com/#!3/474f5/6
edit:
to meet all 3 conditions:
SELECT *
FROM X
WHERE T LIKE '%[0-9]%'
AND T LIKE '%-%'
AND T LIKE '%,%'
see: http://sqlfiddle.com/#!3/86328/1
Maybe not the most beautiful but a working solution.

Can't cut and convert a string - weird format

This question is almost the same with one of my previous questions, which can be found HERE
I have a field named: pa_value which keeps varchar records
Now this field contains records like:
0,5582
0,6985
-0,1589
0,9856
-0,6589
I'm getting these results using the following code:
CAST (replace (p7.pa_value ,'%','') AS float (3,0)) as TotalMargin
What I'm trying to do is to remove everything and leave just 5 characters(or 6 if there is a -(minus) infront of the string).
It should be looking like this:
55.82
69.85
-15.89
98.56
-65.89
I tried to cast it as a float and then to convert it to integer. I also tried the floor command, which is not for my case, without any success. I'm always getting a syntax error message. I believe that there is no way to do this
SELECT p7.pa_value=CASE WHEN LEFT( p7.pa_value,1)='-' THEN '-' +
CONVERT(varchar(max),CONVERT(float,substring(p7.pa_value,4,4))/100) ELSE
CONVERT(varchar(max),CONVERT(float,substring(p7.pa_value,3,4))/100) END
FROM <table_name>
What is being done ..
Check if starting character is '-'.
If yes then extract string starting from position 4 else starting
from position 3.
The inner convert function converts string to float for division and
the outer convert changes back the resultant value back to varchar
type.
If you know there are always four digits after the comma, you could use this, though I don't believe it's perfect:
CONVERT(NUMERIC(9,2), REPLACE(REPLACE(p7.pa_value, '%', ''), ',', '')) / 100

Replacing an Unknown Value with SQL Replace

I'm probably missing something really obvious here, but this has been a bear to search for on Google (Maybe I don't have the right terminology).
I want to replace an unknown value with another value from a temp table. I know the length of the value so my thought was to use underscores as you would in a LIKE statement. The following DOES NOT work however:
UPDATE MyTable
SET Name =
Replace(Name, '__SomeString', TempTable.value + ' SomeString')
FROM MyTable INNER JOIN TempTable
ON Name LIKE TempTable.Name
This is MS SQL 2000 FWIW.
EDIT: To try and clarify it looks like the underscore '_' wildcard that is used in a LIKE statement is taken literally inside of the replace function. Is there another way?
Any thoughts?
UPDATE MyTable
SET Name =
CASE WHEN (Name like '_SomeString')
THEN TempTable.value + SUBSTRING(Name,2,LEN(Name)-1)
ELSE Name END
FROM MyTable INNER JOIN TempTable
ON MyTable.Name = TempTable.Name
WHERE MyTable.Name = 'TheNameToReplace' -- I don't know if it will be for a specific name hence the where...
This will then replace 'SomeString' in the Name field, with the value from TempTable.value
Is this what you were looking for or something else?
Perhaps you can use stuff instead of replace. You need to know the start position in the string where you want to replace the characters and you need to know the length of the expression that is to be replaced. If you don't know that perhaps you can use charindex or patindex to figure that out.
select stuff('A123', 1, 1, 'B ')
Result:
(No column name)
B 123
Would somethi8ng like this work?
UPDATE mytable
SET field1 = 'A' + SUBSTRING(field1,2,LEN(field1))
WHERE LEFT(field1) IN (0,1,2,3,4,5,6,7,8,9)
Apparently it is not possible to use wild cards in the REPLACE function. This is the closest match on SO that I could find: MySQL Search & Replace with WILDCARDS - Query While the link is for MySQL I believe it is true for MS SQL as well.
The other answers here are all creative solutions to the problem, but I ended up going the brute force route.