I have table called ExamInfo. In that table the column Sub1 is of the type VARCHAR(50). The Sub1 column contains numeric, null and non-numeric data.
I want to select from ExamInfo where the data in Sub1 is greater than 81.
Here is my query:
select *
from Exam
where cast(sub1 as int) > 81`.
But it fails to cast resulting in an error.
Since your column contains mixed information and the cast is applied to the whole column, you need to make sure you only attempt to cast actual numeric values:
select *
from Exam
where case when ISNUMERIC(sub1) =1
and CHARINDEX('.', sub1) = 0
and sub1 >= -2147483648
and sub1 <= 2147483647
then cast(sub1 as int)
else 0
end > 81
This is an example on how to do it in SQL Server.
There is one more point of attention in this query and that is "Globalization". The '.' we are checking for as decimal point is not everywhere used as decimal point. If you have a localized SQL Server you can grab the correct decimal separator by doing
DECLARE #decimal_separator char(1)
set #decimal_separator = SUBSTRING(CONVERT(CHAR(3), CONVERT(NUMERIC(2,1), 1.0/2)), 2, 1)
Which would turn the query into:
DECLARE #decimal_separator char(1)
set #decimal_separator = SUBSTRING(CONVERT(CHAR(3), CONVERT(NUMERIC(2,1), 1.0/2)), 2, 1)
select *
from Exam
where case when ISNUMERIC(sub1) =1
and CHARINDEX(#decimal_separator, sub1) = 0
and sub1 >= -2147483648
and sub1 <= 2147483647
then cast(sub1 as int)
else 0
end > 81
It looks like some of the data in sub1 cannot be cast as an int. Check the data for non numeric data.
Try this:
SELECT * FROM ExamInfo
WHERE CAST( (CASE
WHEN ISNUMERIC(Sub1) <> 1
THEN NULL
--Ignore any decimal value
WHEN ISNUMERIC(Sub1 + '.0e0') <> 1
THEN NULL
WHEN CAST(Sub1 AS NUMERIC(38, 0)) BETWEEN -2147483648 AND 2147483647
THEN Sub1
ELSE null
END) AS INT ) > 81;
Related
This query worked perfectly until the moment I went in for vacations, now itdoes not run anymore and does not merge, dont know what it can be
MERGE INTO STG_FATO_MACRO_GESTAO AS FAT
USING(SELECT DISTINCT
COD_EMPRESA
,FUN.MATRICULA AS FUN_MAT
,APR.MATRICULA AS APR_MAT
,FUN.CPF AS FUN_CPF
,APR.CPF AS APR_CPF
,APR.DAT_DESLIGAMENTO
,YEAR(APR.DAT_DESLIGAMENTO)*100+MONTH(APR.DAT_DESLIGAMENTO) AS DESL
,FUN.DATA_ADMISSAO
,YEAR(FUN.DATA_ADMISSAO)*100+MONTH(FUN.DATA_ADMISSAO) AS ADM
, CASE WHEN YEAR(APR.DAT_DESLIGAMENTO)*100+MONTH(APR.DAT_DESLIGAMENTO) <= YEAR(FUN.DATA_ADMISSAO)*100+MONTH(FUN.DATA_ADMISSAO) THEN 1 ELSE 0 END AS ADMITIDO
,CASE WHEN FUN.DATA_ADMISSAO <= (APR.DAT_DESLIGAMENTO + INTERVAL '90' DAY) THEN 1 ELSE 0 END AS APR_90
FROM (SELECT CPF,DATA_ADMISSAO, MATRICULA, COD_EMPRESA FROM DIM_FUNCIONARIO
WHERE PROFISSAO NOT LIKE '%APRENDIZ%') AS FUN
INNER JOIN (SELECT DISTINCT
CPF,DAT_DESLIGAMENTO,MATRICULA
FROM HST_APRENDIZ
WHERE FLAG_FECHAMENTO = 2
AND DAT_DESLIGAMENTO IS NOT NULL) AS APR
ON FUN.CPF = APR.CPF) AS APR_90
ON FAT.COD_EMPRESA = APR_90.COD_EMPRESA
AND FAT.MATRICULA = APR_90.FUN_MAT
AND APR_90.APR_90 = 1
AND APR_90.ADMITIDO = 1
WHEN MATCHED THEN
UPDATE SET APRENDIZ_EFETIVADO_90 = 1
;
when running this query returns me this error:
"The search condition must fully specify the Target table primary index and partition column(s) and expression must match INSERT specification primary index and partition column(s). "
I have a column by the name 'Date' these dates are in format m/d/yyyy, when i query "Select Date from table_nm where Date between '1/2/2015' and '1/9/2015' i get wrong results.
"1/2/2015"
"1/5/2015"
"1/6/2015"
"1/7/2015"
"1/8/2015"
"1/9/2015"
"1/20/2015"
"1/21/2015"
"1/22/2015"
"1/23/2015"
"1/26/2015"
"1/27/2015"
"1/28/2015"
"1/29/2015"
"1/30/2015"
Your issue is that the dates are not in a format that SQLite accepts.
Valid formats can be found here SQL As Understood By SQLite - Date And Time Functions - Time Strings
The format used for your dates is particularity awkward as both months and days can be either 1 or 2 characters. The most likely suitable format would be YYYY-MM-DD e.g. 2015-01-30.
You could use the following as a basis of a solution :-
SELECT *,
CASE
WHEN CAST(month AS INTEGER) < 10 AND CAST(dayinmonth AS INTEGER) < 10 THEN year||'-0'||month||'-0'||dayinmonth
WHEN CAST(month AS INTEGER) < 10 AND CAST(dayinmonth AS INTEGER) >= 10 THEN year||'-0'||month||'-'||dayinmonth
WHEN CAST(month AS INTEGER) >= 10 AND CAST(dayinmonth AS INTEGER) < 10 THEN year||'-'||month||'-0'||dayinmonth
WHEN CAST(month AS INTEGER) >= 10 AND CAST(dayinmonth AS INTEGER) >= 10 THEN year||'-'||month||'-'||dayinmonth
END AS newdate
FROM (
SELECT
*,
substr(date,length(date)-3) AS year,
substr(date,1,instr(date,'/')-1) AS month,
substr(
substr(date, instr(date,'/')+1),
1,
instr(substr(date, instr(date,'/')+1),'/') -1
)
AS dayinmonth
FROM mytable002
)
WHERE newdate BETWEEN '2015-01-02' AND '2015-01-09'
Testing Results :-
The table mytable002 used for testing is as per :-
It actually has more rows
date2 and date3 were added to help demonstrate the inclusion of other columns.
The resultant output is :-
Notes
mytable002 would have to be changed accordingly.
the resultant data includes additional columns (original are underlined blue new columns are highlighted)
As * is used all original columns will be available in the resultant data
Extra re comment :-
Thanks , i have imported this data using python into sqlite,
converting each and every row would not be easy.
The above could be basis for a very easy conversion. You could add a column and then store the re-formatted date, based upon the above, into that column.
e.g. :-
ALTER TABLE mytable002 ADD COLUMN newcolumn TEXT;
WITH updatedata (newdate,olddate) AS (
SELECT
CASE
WHEN CAST(month AS INTEGER) < 10 AND CAST(dayinmonth AS INTEGER) < 10 THEN year||'-0'||month||'-0'||dayinmonth
WHEN CAST(month AS INTEGER) < 10 AND CAST(dayinmonth AS INTEGER) >= 10 THEN year||'-0'||month||'-'||dayinmonth
WHEN CAST(month AS INTEGER) >= 10 AND CAST(dayinmonth AS INTEGER) < 10 THEN year||'-'||month||'-0'||dayinmonth
WHEN CAST(month AS INTEGER) >= 10 AND CAST(dayinmonth AS INTEGER) >= 10 THEN year||'-'||month||'-'||dayinmonth
END AS newdate,
date AS olddate
FROM (
SELECT
*,
substr(date,length(date)-3) AS year,
substr(date,1,instr(date,'/')-1) AS month,
substr(
substr(date, instr(date,'/')+1),
1,
instr(substr(date, instr(date,'/')+1),'/') -1
)
AS dayinmonth
FROM mytable002
)
)
UPDATE mytable002
SET newcolumn = (
SELECT newdate
FROM updatedata
WHERE mytable002.date = olddate
)
;
I am trying to find the difference between two dates (Currentdate-Duedate)
I used Julianday('now')-Julianday(T1.DD), the results appear fine when the result are positive (when currentDate > DueDate), but results are incorrect when DueDate > Current Date (negative results appear 1 day lower than expected).
Following statement was tried:
Select( CAST((Julianday('now')-Julianday(T1.DD)) As Integer)
Example format of the column DD in Database 2017-07-21 00:00:00.
select case when julianday('now') > julianday(T1.DD)
then cast (julianday('now') - julianday(T1.DD) as int)
else cast ((julianday(T1.DD) - julianday('now') + 1) as int)
end
from test;
UPDATE 1:
select cast(julianday('now') as int) - cast(julianday(T1.DD) as int)
from test;
UPDATE 2:
select cast(julianday(date('now') )- julianday(date(T1.DD)) as int )
from test;
I am running the following stored precedure.
The result set is binded on a gridView control.
#EmbossLine varchar(20),
#TransactionTypeID int,
#DateFrom datetime,
#DateTo datetime
AS
Select
pt.TransactionDate,
m.MerchantName1,
pt.TerminalID,
pt.SequenceNumber,
tt.TransactionType,
case TT.TransactionTypeID when 0 then PT.TotalAmount else 'null' end 'PointsEarned',
case TT.TransactionTypeID when 2 then PT.TotalAmount else 'null' end 'PointsRedemeed'
from POS_Transactions PT
inner join TransactionType TT on TT.TransactionTypeID = PT.TransactionTypeID
inner join CardBalance CB on CB.PAN = PT.PAN
inner join Terminal T on T.TerminalID = PT.TerminalID
inner join Merchant M on M.MerchantID = T.MerchantID
where
(PT.TransactionDate>=#DateFrom and PT.TransactionDate<=#DateTo)
and (PT.TransactionTypeID = #TransactionTypeID or #TransactionTypeID ='-999')
and(PT.PAN=#EmbossLine or PT.PAN='-999')
order by PT.TransactionDate desc
Actually what Im trying to do is, I want to print null whenever my TransactionTypeID is not equal to 0 or 2. but it throws a runtime exception
Cannot convert a char value to money. The char value has incorrect syntax.
I know it is a conversion issue and want to know how can I print some value when my conditions evaluates to false
Change these two lines:
case TT.TransactionTypeID when 0 then PT.TotalAmount else 'null' end 'PointsEarned',
case TT.TransactionTypeID when 2 then PT.TotalAmount else 'null' end 'PointsRedemeed'
to this:
case TT.TransactionTypeID when 0 then PT.TotalAmount else null end 'PointsEarned',
case TT.TransactionTypeID when 2 then PT.TotalAmount else null end 'PointsRedemeed'
You want to produce a null value in your else condition. You are currently producing the word 'null' which is where the conversion is failing - you can't convert the word (char data type) 'null' to the money datatype.
EDIT:
You will need to cast the values to a string to do this. But that would mean instead of returning the money datatype to your client, you would be returning a string.
This sort of thing should really be handled in the client and not in SQL Server. In anycase try this to convert everything to a string:
case TT.TransactionTypeID when 0 then Cast(PT.TotalAmount as varchar(50)) else 'null' end 'PointsEarned',
case TT.TransactionTypeID when 2 then Cast(PT.TotalAmount as varchar(50)) else 'null' end 'PointsRedemeed'
Do this.
case TT.TransactionTypeID when 0 then cast(PT.TotalAmount as varchar) else 'null' end 'PointsEarned',
case TT.TransactionTypeID when 2 then cast(PT.TotalAmount as varchar) else 'null' end 'PointsRedemeed'
just cast TotalAmount to varchar, it should work.
I am doing a long to string conversion using java in following way.
Long longValue = 367L;
String str = Long.toString(longValue, 36).toUpperCase();
this is returning me as value A7. how can achieve this in doing oracle sql.
UPDATED:
Hi, I have analyzed how java code is working then wanted to implement the same thing in procedure.
First point is Input vaues. LONG and Radix. in my case Radix is 36. so i will have values from 1..9A...Z0 It picks up the values from this set only.
Second point Long value as input. we have to divide this value with radix. if the quotient is more than 36 again we need to divide.
For eaxmple 367 then my converted value is 10(quotient) 7(remainder) that is A7.
3672 converted value is 102 0 i need to do again for 102 that is 2 -6 so my final value will be 2-6 0 that is 2U0(- means reverse the order).
UPDATE 2:
Using oracle built in functions we can do this. this was solved by my friend and gave me a function.I want to thank my friend. this will give me an out put as follows.
367 then my converted value is 10(quotient) 7(remainder) that is *A*7.(I modified this to my requirement).
FUNCTION ENCODE_STRING(BASE_STRING IN VARCHAR2,
FROM_BASE IN NUMBER,
TO_BASE IN NUMBER)
RETURN VARCHAR2
IS
V_ENCODED_STRING VARCHAR(100);
BEGIN
WITH N1 AS (
SELECT SUM((CASE
WHEN C BETWEEN '0' AND '9'
THEN TO_NUMBER(C)
ELSE
ASCII(C) - ASCII('A') + 10
END) * POWER(FROM_BASE, LEN - RN)
) AS THE_NUM
FROM (SELECT SUBSTR(BASE_STRING, ROWNUM, 1) C, LENGTH(BASE_STRING) LEN, ROWNUM RN
FROM DUAL
CONNECT BY ROWNUM <= LENGTH(BASE_STRING))
),
N2 AS (
SELECT (CASE
WHEN N < 10
THEN TO_CHAR(N)
ELSE CHR(ASCII('A') + N - 10)
END) AS DIGI, RN
FROM (SELECT MOD(TRUNC(THE_NUM/POWER(TO_BASE, ROWNUM - 1)), TO_BASE) N, ROWNUM RN
FROM N1
CONNECT BY ROWNUM <= TRUNC(LOG(TO_BASE, THE_NUM)) + 1)
)
SELECT SYS_CONNECT_BY_PATH(DIGI, '*') INTO V_ENCODED_STRING
FROM N2
WHERE RN = 1
START WITH RN = (SELECT MAX(RN) FROM N2)
CONNECT BY RN = PRIOR RN - 1;
RETURN V_ENCODED_STRING;
IN PL/SQL (or Oracle SQL) you have the a function called TO_CHAR.
http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions181.htm
It is not possible to do it in the pure SQL. You have to use PL/SQL.
Simple example how to do it PL/SQL:
CREATE TABLE long_tbl
(
long_col LONG
);
INSERT INTO long_tbl VALUES('How to convert the Long value to String using sql');
DECLARE
l_varchar VARCHAR2(32767);
BEGIN
SELECT long_col
INTO l_varchar
FROM long_tbl;
DBMS_OUTPUT.PUT_LINE(l_varchar);
END;
-- How to convert the Long value to String using sql
There is TO_LOB function but it can only by used when you insert data into table.
http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions185.htm
You can apply this function only to a LONG or LONG RAW column, and
only in the select list of a subquery in an INSERT statement.
There is also other, more proper way to do it by using "dbms_sql.column_value_long" but this gets complicated (fetching of the LONG column and appending to the CLOB type.)
http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_sql.htm#i1025399
(Oracle Database PL/SQL Packages and Types Reference)