Searching a varchar field for numeric values of a certain range - sql

Using Oracle SQL Developer v3.2.20.09:
I have a table of data where, among all the other data, I have a column of all numeric results (for examples' sake, RESULT_NUM) but due to the way it is stored and used, is a varchar2 field. I need to pull all the records for the Body Temperature Codes (BT, TEMP, TEMPERATURE in the VT_CODE field) where result_num > 100 (everything is in Fahrenheit, so searching on the result alone will work).
So, my simple statement is:
Select * from VITALS where VT_CODE in ('BT', 'TEMP', 'TEMPERATURE');
This kicks me back all of the body temp records, which is over 2M. Now I need to refine it to get results that are over over 100.
When I try to add "and result_num > 100" I get an error because it is a varchar field I am trying to search with a number.
When I try to add "and result_num > '100'", it executes without error because it is a character value, but it returns everything greater than 1, not 100, which is everything, obviously.
Please help.

Try the following
and convert(int,result_num) > 100
or
and CAST(result_num as INTEGER) > 100

Related

SQL Decode format numbers only

I want to format amounts to salary format, e.g. 10000 becomes 10,000, so I use to_char(amount, '99,999,99')
SELECT SUM(DECODE(e.element_name,'Basic Salary',to_char(v.screen_entry_value,'99,999,99'),0)) Salary,
SUM(DECODE(e.element_name,'Transportation Allowance',to_char(v.screen_entry_value,'99,999,99'),0)) Transportation,
SUM(DECODE(e.element_name,'GOSI Processing',to_char(v.screen_entry_value,'99,999,99'),0)) GOSI,
SUM(DECODE(e.element_name,'Housing Allowance',to_char(v.screen_entry_value,'99,999,99'),0)) Housing
FROM values v,
values_types vt,
elements e
WHERE vt.value_type = 'Amount'
this gives error invalid number because not all values are numbers until value_type is equal to Amount but I guess decode check all values anyway although what I know is that the execution begins with from then where then select, what's going wrong here?
You said you added decode(...), but it looks like you might have actually added sum(decode(...)).
You are converting your values to strings with to_char(v.screen_entry_value,'99,999,99'), so your decode() generates a string - the default 0 will be converted to '0' - giving you a value like '1,234,56'. Then you are aggregating those, so sum() has to implicitly convert those strings to numbers - and it is throwing the error when it tries to do that:
select to_number('1,234,56') from dual
will also get "ORA-01722: invalid number", unless you supply a similar format mask so it knows how to interpret it. You could do that, e.g.:
SUM(to_number(DECODE(e.element_name,'Basic Salary',to_char(v.screen_entry_value,'99,999,99'),0),'99,999,99'))
... but it's maybe more obvious that something is strange, and even if you did, you would end up with a number, not a formatted string.
So instead of doing:
SUM(DECODE(e.element_name,'Basic Salary',to_char(v.screen_entry_value,'99,999,99'),0))
you should format the result after aggregating:
to_char(SUM(DECODE(e.element_name,'Basic Salary',v.screen_entry_value,0)),'99,999,99')
fiddle with dummy tables, data and joins.

Querying xmin column in Postgres yields xid in query

I am trying to sequentially grab the first record that matches the greater than or equal query on the xmin column compared to an incrementing integer in PostgreSQL. My query looks like this at execution time:
SELECT xmin, column1, column2, column3 FROM records WHERE xmin >= $1 LIMIT 1 ;
And then at call time, I pass the args 1 to the query through the standard sql.QueryRow function.
However, I expect to be getting back a row, instead I'm returned the following error.
pq: operator does not exist: xid >= unknown
Two things here: I can't figure out where xid is coming from since I never query for it, and I can't figure out why the placeholder value is not being added correctly either. The argument is getting passed to the query at call time, it's not nil or anything, but the Postgres engine doesn't like my query.
If you had 'blah' >= 4 the error would say something like operator does not exist: text >= integer. The xid is a type not a column. It isn't an integer and can't directly be compared to one.
You can do xid::text::bigint >= $1 if you really want to but make sure you understand the implications of transaction wrap-around.
Let me repeat that last point - go away and read up about how PostgreSQL transaction IDs work before you start trying to compare them numerically.

Query to ignore rows which have non hex values within field

Initial situation
I have a relatively large table (ca. 0.7 Mio records) where an nvarchar field "MediaID" contains largely media IDs in proper hexadecimal notation (as they should).
Within my "sequential" query (each query depends on the output of the query before, this is all in pure T-SQL) I have to convert these hexadecimal values into decimal bigint values in order to do further calculations and filtering on these calculated values for the subsequent queries.
--> So far, no problem. The "sequential" query works fine.
Problem
Unfortunately, some of these Media IDs do contain non-hex characters - most probably because there was some typing errors by the people which have added them or through import errors from the previous business system.
Because of these non-hex chars, the whole query fails (of course) because the conversion hits an error.
For my current purpose, such rows must be skipped/ignored as they are clearly wrong and cannot be used (there are no medias / data carriers in use with the current business system which can have non-hex character IDs).
Manual editing of the data is not an option as there are too many errors and it is not clear with what the data must be replaced.
Challenge
To create a query which only returns records which have valid hex values within the media ID field.
(Unfortunately, my SQL skills are not enough to create the above query. Your help is highly appreciated.)
The relevant section of the larger query looks like this (xxxx is where your help comes in :-))
select
pureMediaID
, mediaID
, CUSTOMERID
,CONTRACT_CUSTOMERID
from
(
select concat('0x', Replace(Ltrim(Replace(mediaID, '0', ' ')), ' ', '0')) AS pureMediaID
--, CUSTOMERID
, *
from M_T_CONTRACT_CUSTOMERS
where mediaID is not null
and mediaID like '0%'
and xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
) as inner1
EDIT: As per request I have added here some good and some bad data:
Good:
4335463357
4335459809
1426427996
4335463509
4335515039
4335465134
4427370396
4335415661
4427369036
4335419089
004BB03433
004e7cf9c6
00BD23133
00EE13D8C1
00CCB5522C
00C46522C
00dbbe3433
Bad:
4564589+
AB6B8BFC.8
7B498DFCnm
DB218DFChb
d<tgfh8CFC
CB9E8AFCzj
B458DFCjhl
rytzju8DFC
BFCtdsjshj
DB9888FCgf
9BC08CFCyx
EB198DFCzj
4B628CFChj
7B2B8DFCgg
After I did upgrade the compatibility level of the SQL instance to SQL2016 (it was below 2012 before) I could use try_convert with same syntax as the original convert function as donPablo has pointed out. With that the query could run fully through and every MediaID which is not a correct hex value gets nicely converted into a null value - really, really nice.
Exactly what I needed.
Unfortunately, the solution of ALICE... didn't work out for me as this was also (strangely) returning records which had the "+" character within them.
Edit: The added comment of Alice... where you create a calculated field like this:
CASE WHEN "KEY" LIKE '%[^0-9A-F]%' THEN 0 ELSE 1 end as xyz
and then filter in the next query like this:
where xyz = 1
works also with SQL Instances with compatibility level < SQL 2012.
Great addition for people which still have to work with older SQL instances.
An option (although not ideal in terms of performance) is to check the characters in the MediaID through a case statement and regular expression
Hexadecimals cannot contain characters other than A-F and numbers between 0 and 9
CASE WHEN MediaID LIKE '%[0-9A-F]%' THEN 1 ELSE 0 END
I would recommend writing a function that can be used to evaluate MediaID first and checks if it is hexadecimal and then running the query for conversion

Conditional update query to pad alphanumeric values in MS Access

I have an Access table with a field that contains alphanumeric values (1234, 123A, 12A34, ABC3, etc). I am trying to create a conditional update query to add leading zeros to bring all values that contain at least 1 letter up to five characters but none to the only numeric values (eg 123, 00A12, 0000X).
My current code looks like:
UPDATE MyTable SET MyTable!Field = Format(Field, String(5, "0")) WHERE MyTable!Field LIKE '*[A-Z]*'
When I run the query, I don't get any error messages but it also fails to add any leading zeros.
I've also tried Format(Field, "00000") using Not Like and '*[0-9]*' or '*[0123456789]*' etc.
Interestingly, when I run a query by itself to select any of the values containing a letter (Like '*[A-Z]*'), it correctly pulls all 1000 values that need to be updated but when I add the conditional, it fails. Similarly, I've been successful in the past with adding leading zeros the entire field using Format(Field), String(5, "0") but it also fails when I add a conditional.
I'm pretty new to Access and SQL, so I feel like I've probably misunderstood the syntax somewhere. Or is there something else I should be doing?
Format() is wrong function to use.
If every value in field is 5 characters or less, consider:
UPDATE MyTable SET Field = String(5-Len(Field), "0")) & Field WHERE Not IsNumeric(Nz(Field,0))

Update Query to get rid of "AM" & "PM" in string

I wrote a basic update query:
Update WA SET WA.Time_Updated = Replace(Time_Updated, 'PM', ' ');
to which I don't get any real error message other than
Microsoft can't update 251 records etc due to type conversion error
There are 5000 records in there. I have the date column as Date/Time and all my other columns (non-dates) as Short Text. The query just does not update anything in the table and keeps it previously was. Any ideas?
Just convert your text times to Date values:
Select *, TimeValue([Time_Updated]) As TimeUpdated From WA
Then, when you display TimeUpdate, format the value as you like.
Can deal with the imported structure.
Consider:
Hour("12:03:00 PM") + Minute("12:03:00 PM")/60 + Second("12:03:00 PM")/3600
This calculates to 12.05
So don't change the raw data, calculate in query. Just use your field name in place of the static value in the expression.