SQL - Using logical operators in a UDF case statement - logical-operators

So it took a while for me to figure out how to create my first UDF but after I fixed it, I figured my next one would be a piece of cake. Unfortunately, it hasn't been the case. I'm pulling a field (ORIG_CLAIM, float) and I want to categorize that number. Here's my code:
CREATE FUNCTION [dbo].[fnOC_LEVEL](#ORIG_CLAIM float)
RETURNS nvarchar(255)
AS
BEGIN
DECLARE #result as varchar(255);
SELECT #result = case #ORIG_CLAIM
when < 1000 then 'A_Under 1000'
when >= 1000 and <= 4999.99 then 'B_1000-4999'
when >= 5000 and <= 7499.99 then 'C_5000-7499'
when >= 7500 and <= 9999.99 then 'D_7500-9999'
when >= 10000 and <= 14999.99 then 'E_10000-14999'
when >= 15000 and <= 19999.99 then 'F_15000-19999'
when >= 20000 then 'G_Over 20000'
END
RETURN #result
END
GO
I'm getting the error "Incorrect syntax near '<'". Can anyone wee what I might be doing wrong?

I think you may have to specify the comparison values as float. For example:
when < 1.0E3 then 'A_Under 1000'
when >= 1.0E3 and <= 4.99999E3 then 'B_1000-4999'
etc.

Related

what is different between using Variable and not in Mariadb?

I just want to get some hint. Is there a type issue?
issue case.
SET #ids = '4094,8562,11144,3017,5815,11121,1957,4095,8563,11145,3018,5816,8527,11122,1959,4096,8564,3020,5817,8528,11123,1961,4097,8571,3021,6020,8535,11128,1962,5181,8572,3581,6021';
this #ids value is actually collected by GROUP_CONCAT() from the subquery;
SELECT
ifnull(sum(case when a.student IS NOT NULL then total END), 0)
from
tb_class a
WHERE
a.id IN (#ids)
and a.date >= '2023-02-01' AND a.DATE <= '2023-02-02'
==> 0
correct case2.
SELECT
ifnull(sum(case when a.student IS NOT NULL then total END), 0)
from
tb_class a
WHERE
a.id IN (4094,8562,11144,3017,5815,11121,1957,4095,8563,11145,3018,5816,8527,11122,1959,4096,8564,3020,5817,8528,11123,1961,4097,8571,3021,6020,8535,11128,1962,5181,8572,3581,6021)
and a.date >= '2023-02-01' AND a.DATE <= '2023-02-02'
==> 54
I got answer from googling. use function FIND_IN_SET()
SELECT
ifnull(sum(case when a.student IS NOT NULL then total END), 0)
from
tb_class a
WHERE
FIND_IN_SET(a.id, #ids)
and a.date >= '2023-02-01' AND a.DATE <= '2023-02-02'
Variables store single values, not lists. Your #ids is just a string that happens to have a comma separated list of numbers. The IN operator only compares against an explicit list; what you are doing is no different than a.id = #ids (which will actually be true, with a warning, for the first number in the list if id is a numeric type, since the string will be converted to a number and the trailing non-numeric portion discarded).
Sometimes you do want to work with a string containing a list of ids such as this, for instance if you have a query that reads many rows that you want to use to produce a small list of ids to update, without the update locking those all the rows read. Then you can use dynamic sql:
SET #ids = '4094,8562,...';
SET #sql = concat('select * from a where a.id in (',#ids,')');
prepare stmt from #sql;
execute stmt;
deallocate prepare stmt;
Or, in mariadb since 10.2,
EXECUTE IMMEDIATE concat('select * from a where a.id in (',#ids,')');
Another alternative is to use FIND_IN_SET, as shown in another answer, but that will not use an index to look up ids, so may be inefficient.

Using Today() function in a query with standard dates in Google Sheets

I am working with data output from a program and then uploaded into google sheets that looks like the following:
So my timestamp is in the format of 1/2/2020 8:56 (and I totally get that query has to work with yyyy-mm-dd format, which is why we have to do the acrobatics)
I'm using the query function to pull needed data into different tabs and would like to use the Today() or Now() function to only pull the last 12 or 24 hours results and I can't seem to get it to work. (Mind that I'm just learning the query function)
So I have
=query(RawDataUpload!A:I,"select * where A is not null and A >= date '2020-01-02' and B = 'Buying' and H > 0 and H < 50000 Order by D, H desc")
and it works ok, but I have to put in the date each new day and at 8am it's only 8 hours of data instead of 12 (more of a problem at 2am)
I've tried using a few examples and I keep getting a parsing error or some error
=query(RawDataUpload!A:I,"select * where A is not null and A >= date '"&TEXT(TODAY(),"yyyy-mm-dd")&"'",1 and B = 'Buying' and H > 0 and H < 50000 Order by D, H desc")")
=query(RawDataUpload!A:I,"select * where A is not null and A >= date '"&TEXT(TODAY(),"yyyy-mm-dd")&"'" and B = 'Buying' and H > 0 and H < 50000 Order by D, H desc")")
[I see & thrown in but no explanation of why or what it does, and same to the " " instead of ' ' and why the mix mash of using both in the examples of using today() and I've found 0 examples of using the now instead of the date function in my googling.]
So is there a way to limit by date (and possibly time) using the today() or Now()-12 function embedded in the Query function in google sheets?
Try
=query(RawDataUpload!A:I,"select * where A is not null and A >= date '"&TEXT(TODAY(),"yyyy-mm-dd")&"' and B = 'Buying' and H > 0 and H < 50000 Order by D, H desc")
The & is used to join a string to form a formula.
For example, if you want the formula to read:
... and A >= date '2020-01-03' and B =....
But you'd like the date to be today's date, you would use:
...and A >= date '"&TEXT(TODAY(),"yyyy-mm-dd")&"' and B =...
The " is used to exit the query string and add the Text() formula. And the & is used to join them.
You can use Filter like this:
= filter ( A2:I,B2:B="Buying",
text(A2:A,"yyyy.mm.dd.hh")>=text(now(),"yyyy.mm.dd.") & "08",
text(A2:A,"yyyy.mm.dd.hh")<=text(now()+0,"yyyy.mm.dd.") & "16"
)
begin from row 2 because in row 1 are column titles
Remarks1 : 08 & 16 are for limit hour begin from 08 and last 16, can be changed
Remarks2 : +0 only this day, if change to +1 this day and tomorrow and so on

Difference between two dates appear incorrectly

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;

How to convert the Long value to String using sql

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)

How to cast varchar to int in sql

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;

Resources