Why I get error message "Invalid number" since UserID is NUMBER - string

I am little bit confusing and have no idea where I made mistake.
SELECT uta.StartDate, uta.EndDate FROM user_timesheets_absence uta
WHERE uta.UserID = 353
AND uta.Approved = 'true'
AND '2020-03-06' BETWEEN TO_DATE(uta.StartDate,'YYYY-MM-DD') AND TO_DATE(uta.EndDate,'YYYY-MM-DD') + INTERVAL '1' DAY
In following query I get error
ORA-01722: invalid number
I try to understand where the error is, but when I realize query a deeper I can not see where the error is.
ABSENCETYPE VARCHAR2(255 CHAR)
ANSWER VARCHAR2(500 CHAR)
APPROVED NUMBER(10,0)
COMMENT_ CLOB
DAYS NUMBER(10,0)
ENDDATE VARCHAR2(50 CHAR)
ISANSWERED NUMBER(10,0)
ISREJECTED NUMBER(10,0)
STARTDATE VARCHAR2(50 CHAR)
USERABSENCEID NUMBER(10,0)
USERHASSEEN VARCHAR2(500 CHAR)
USERID NUMBER(10,0)
WIDTH NUMBER(10,0)
When I insert data into table, I use this kind of data and It works fine. But when I use SELECT statment I get error. I hope the error was UserID but it wasn't.
Insert into DB.USER_TIMESHEETS_ABSENCE (ABSENCETYPE,ANSWER,APPROVED,DAYS,ENDDATE,ISANSWERED,ISREJECTED,STARTDATE,USERABSENCEID,USERHASSEEN,USERID,WIDTH) values ('1','ne',0,8,'2020-02-06',1,1,'2020-01-30',89,'1',348,160);
Can someone tell me, where I made mistake ? What is wrong here ?

There is more than one problem in this query.
Firstly, here:
AND uta.Approved = 'true'
approved is a number, but you are comparing it against string 'true'. This does not work. Use a literal number on the right side of the equal sign.
Then, here:
AND '2020-03-06'
BETWEEN TO_DATE(uta.StartDate,'YYYY-MM-DD')
AND TO_DATE(uta.EndDate,'YYYY-MM-DD') + INTERVAL '1' DAY
You are comparing a string against dates. This won't work. You probably want a literal date on the left side of between. I would also recommend using + 1 rather than the interval syntax, which should be reserved to timestamps:
AND DATE '2020-03-06'
BETWEEN TO_DATE(uta.StartDate,'YYYY-MM-DD')
AND TO_DATE(uta.EndDate,'YYYY-MM-DD') + 1

Why are STARTDATE and ENDDATE defined as strings rather than date. Not using the correct data types is a surefire way to introduce data corruption issues. That's certainly where I would start looking.
The other thing is, always use explicit casting when converting strings into dates (or numbers) and vice versa. In this case you should use a date literal. Instead of
AND '2020-03-06' BETWEEN TO_DATE(uta.StartDate,'YYYY-MM-DD') AND TO_DATE(uta.EndDate,'YYYY-MM-DD')
use
AND date '2020-03-06' BETWEEN TO_DATE(uta.StartDate,'YYYY-MM-DD') AND TO_DATE(uta.EndDate,'YYYY-MM-DD')
If you have got data corruption in your date columns and you're on 12c or later you can use VALIDATE_CONVERSATION to filter rows which don't contain valid dates:
SELECT uta.StartDate, uta.EndDate FROM user_timesheets_absence uta
WHERE uta.UserID = 353
AND uta.Approved = 'true'
AND validate_conversion(uta.StartDate,'YYYY-MM-DD') = 1
AND validate_conversion(uta.EndDate,'YYYY-MM-DD') = 1
AND date '2020-03-06' BETWEEN TO_DATE(uta.StartDate,'YYYY-MM-DD') AND TO_DATE(uta.EndDate,'YYYY-MM-DD') + INTERVAL '1' DAY
You can also use this to find invalid date strings:
SELECT *
FROM user_timesheets_absence uta
WHERE validate_conversion(uta.StartDate,'YYYY-MM-DD') = 0
OR validate_conversion(uta.EndDate,'YYYY-MM-DD') = 0

Related

Cognos Report Studio: CASE and IF Statements

I'm very new in using Cognos report studio and trying to filter some of the values and replace them into others.
I currently have values that are coming out as blanks and want to replace them as string "Property Claims"
what i'm trying to use in my main query is
CASE WHEN [Portfolio] is null
then 'Property Claims'
ELSE [Portfolio]
which is giving me an error. Also have a different filter i want to put in to replace windscreen flags to a string value rather than a number. For example if the flag is 1 i want to place it as 'Windscreen Claims'.
if [Claim Windscreen Flag] = 1
then ('Windscreen')
Else [Claim Windscreen Flag]
None of this works with the same error....can someone give me a hand?
Your first CASE statement is missing the END. The error message should be pretty clear. But there is a simpler way to do that:
coalesce([Portfolio], 'Property Claims')
The second problem is similar: Your IF...THEN...ELSE statement is missing a bunch of parentheses. But after correcting that you may have problems with incompatible data types. You may need to cast the numbers to strings:
case
when [Claim Windscreen Flag] = 1 then ('Windscreen')
else cast([Claim Windscreen Flag], varchar(50))
end
In future, please include the error messages.
it might be syntax
IS NULL (instead of = null)
NULL is not blank. You might also want = ' '
case might need an else and END at the bottom
referring to a data type as something else can cause errors. For example a numeric like [Sales] = 'Jane Doe'
For example (assuming the result is a string and data item 2 is also a string),
case
when([data item 1] IS NULL)Then('X')
when([data item 1] = ' ')Then('X')
else([data item 2])
end
Also, if you want to show a data item as a different type, you can use CAST

How to save decimal heights in MongoDB

I'm facing this strange problem while saving numeric values in mongodb.
I'm saving height of people in mongodb as Number, so a person with height of 5'.1" is saved as 5.1 and a person with a height of 5'.10" is also saved as 5.1.
I can't change it to string because I have a my search query based on number, ("height" : {"$gte": req.body.height.minimum_height, "$lte": req.body.height.maximum_height}).
I'm sure there must be a way to save specific values to deal with monetary transactions, but I'm not sure how to do it in my scenario.
Any suggestions are welcome !!
Since the height is already a number, it would be better to treat it in metric units and follow the convention that it represents height in centimetres.
When retrieving heights then as #J.F. suggested in the comment it can be formatted in the client app or wherever else it is required.
When storing heights it can be converted to centimetres.
For example 5'10'' becomes (5 x 12 + 10) x 2.54 = 177.8
One solution is to use two fields: the numeric value and the display value.
For 5' 10", the numeric value is 5 + 10/12 which is 5.83333...
irb(main):001:0> 5+(10/12.0)
=> 5.833333333333333
Then use the numeric field for searches and calculations and keep 5' 10" in the display field for rendering to users.
Alternatively you can only store the numeric value and calculate the display value:
irb(main):007:0> i = (5.833333333333333 * 12).round; f = i / 12; i = i % 12
=> 10
irb(main):008:0> f
=> 5
irb(main):009:0> i
=> 10
irb(main):010:0> "#{f}' #{i}\""
=> "5' 10\""
irb(main):011:0>

Spotfire date expression error

In spotfire I have a column property fromDate and toDate which is a Date. I am trying to limit the result of data using expression below. But I keep on encountering this error
Invalid type for function call 'DocumentProperty' on line1, character 19
Limit Expression
[poddate] >= Date(DocumentProperty(${DevInfoYTD}.{Location}.{fromDate})) and
[poddate] <= Date(DocumentProperty(${DevInfoYTD}.{Location}.{toDate}))
If I used the below expression i don't get an error but there is no data shown on the table.
[poddate] >= Date(${DevInfoYTD}.{Location}.{fromDate})
and [poddate] <= Date(${DevInfoYTD}.{Location}.{toDate})
Any ideas on how to fix it?
You don't need a three part identifier. I'm unsure of what that even is supposed to be, but you only need to list the property control.
[poddate] >= Date("${YourPropertyControlName}")
AND
and [poddate] <= Date("${YourOtherPropertyControlName}")

SQLite does not cast to integer

I've created the following select and calculate the "missing" value
select strftime('%d.%m. %H:%M', O_LROU_DEPARTDATE) || ' - ' || O_LROU_IDENT as Ident,
O_LROU_CSLCNTPICKED as 'done',
CAST((O_LROU_CSLCNT - O_LROU_CSLCNTPICKED) as integer) as 'missing'
from RAW_OM36
where (O_LROU_CSLCNT - O_LROU_CSLCNTPICKED) > 0
But the missing value is still a text and not a integer.
Here a picture! What's going wrong?
I have just had the same problem.
It is not clear from your picture how many records are selected. My driver determines the datatype from the first record. If the value in the first record is null then the driver interprets the column as string (32767). If the first record is a valid integer then the column is interpreted as integer.
A possible solution is to change
CAST((O_LROU_CSLCNT - O_LROU_CSLCNTPICKED) as integer)
to
IFNULL(O_LROU_CSLCNT - O_LROU_CSLCNTPICKED), 0)
accepting that changing nulls to zeros might not be acceptable to you application.

Getting a string value that is between two characters

I need to get the value that is between !03 and !03.
Example:
JDC!0320151104!03OUT
I should get following string in return: 20151104
NOTE: The string isn't always 22 characters long, but I am only concerned with the value that is between !03 and !03.
This is what I have so far. I couldn't make any progress further than this:
SELECT
SUBSTRING(
RegStatsID,
CHARINDEX('!', RegStatsID) + 3,
CHARINDEX('!', REVERSE(RegStatsID))
)
From TableX
Great that you found a solution!
This might be better:
By replacing the "!03" with XML-tags you can easily pick the second "node". Your string will be transformed into <x>JDC</x><x>20151104</x><x>OUT</x>:
DECLARE #test VARCHAR(100)='JDC!0320151104!03OUT';
SELECT CAST('<x>' + REPLACE(#test,'!03','</x><x>') + '</x>' AS XML).value('/x[2]','datetime')
One advantage was to get the value between the two "!03" typed. In this case you get a "real" datetime back without any further casts. If the value there is not a datetime (or date) in all cases, you just use nvarchar(max) as type.
Another advantage was: If you - why ever - need the other values later, you just have them with .value('/x[1 or 3]'...)
I was able to get it right by doing following:
SELECT
SUBSTRING(
RegStatsID,
CHARINDEX('!', RegStatsID) + 3,
len(RegStatsID) - CHARINDEX('!', RegStatsID ) - 2 - CHARINDEX('!', Reverse(RegStatsID))
)

Resources