dbms_random.value() in Snowflake - Oracle to snowflake conversion - oracle

Below is the oracle sql query that I got to convert to snowflake. In here, i am blocked in creating dbms_random.value() in snowflake
select emp_id, emp_name, emp_mob,
(case when dbms_random.value() >= 0.85 then 'Y' else 'N' end) as tag
from eds_dwg.employee_data
Can someone help me on this?
Thanks

You can use Snowflake Data generation functions: https://docs.snowflake.com/en/sql-reference/functions-data-generation.html
NORMAL() returns a floating point number with a specified mean and standard deviation. Something like this with correct adaptions of the parameters could to the trick: https://docs.snowflake.com/en/sql-reference/functions/normal.html
An alternative can be using UNIFORM(): https://docs.snowflake.com/en/sql-reference/functions/uniform.html
Example from docs to generate a value between 0 and 1:
select uniform(0::float, 1::float, random()) from table(generator(rowcount => 5));

Related

How to retrieve currency amount as words using oracle sql

In the below code, I am trying to get the amount in words for the value in the AMOUNT column but can't seem to get it right. Anyone with an idea? Below the CREATE VIEW statement:
SELECT GLR3 AS RECEIPT_DOC_NO,
GLANI AS ACCOUNT_NUMBER,
GLSBL AS JDE_NO,
(SELECT YAALPH FROM PRODDTA.F060116 WHERE YAAN8 = T1.GLSBL) AS STAFF_NAME,
CASE GLDGJ WHEN 0 THEN TO_DATE (TO_CHAR (1 + 1900000), 'YYYYDDD')
ELSE TO_DATE (TO_CHAR (GLDGJ + 1900000), 'YYYYDDD') END AS GL_DATE,
GLEXA AS NARRATIVE,
GLLT AS LEDGER_TYPE,
GLSBLT AS SUBLEDGER_TYPE,
GLCRCD AS CURRENCY_CODE,
CASE GLAA WHEN 100 THEN ROUND (GLAA / 100, 2) ELSE ROUND (GLAA / 100, 2)
END AS AMOUNT,
(SELECT TO_CHAR(TO_DATE(T1.GLAA,'J'),'JSP')) FROM DUAL) AS AMOUNT_INWORDS
FROM PRODDTA.F0911 T1;
My code is failing with
ORA-00923: FROM keyword not found where expected.
ORA-00923: FROM keyword not found where expected.
Indicates a syntax error. In this case you have three ( and four ):
(SELECT TO_CHAR(TO_DATE(T1.GLAA,'J'),'JSP')) FROM DUAL) AS AMOUNT_INWORDS
The compiler is not expecting the second ) after 'JSP'.
The scalar cursor is unnecessary, so the simplified and corrected version would be:
TO_CHAR(TO_DATE(T1.GLAA,'J'),'JSP') AS AMOUNT_INWORDS
ORA-01854: julian date must be between 1 and 5373484
5373484 is the Julian date for 31-DEC-9999 which is the maximum date allowed in Oracle. This poses an absolute limit on the number which we can spell using JSP mask ... in one go. However, we can use PL/SQL to break larger numbers into chunks and spell those instead. The inestimable Tom Kyte wrote such a function and published it on the AskTom site. Find it here.
I think the value i'm trying to write in words has decimal values (400.00) hence the ORA-01854 error.
The Tom Kyte I linked to does address that issue further down the page. It's this comment here.
Data retrieved in amount column is preceded by a negative symbol when it shouldn't be,
If you simply want to ignore negative values then apply the ABS() function to give you the absolute value.

Oracle. CAST COLLECT for date datatype

Consider the types:
CREATE OR REPLACE TYPE date_array AS TABLE OF DATE;
CREATE OR REPLACE TYPE number_array AS TABLE OF NUMBER;
CREATE OR REPLACE TYPE char_array AS TABLE OF VARCHAR2(80);
Queries:
WITH q AS
(SELECT LEVEL ID,
TRUNC(SYSDATE) + LEVEL MyDate,
to_char(LEVEL) STRING
FROM dual
CONNECT BY LEVEL < 5)
SELECT CAST(COLLECT(ID) AS number_array)
FROM q;
return collection of numbers
WITH q AS
(SELECT LEVEL ID,
TRUNC(SYSDATE) + LEVEL MyDate,
to_char(LEVEL) STRING
FROM dual
CONNECT BY LEVEL < 5)
SELECT CAST(COLLECT(STRING) AS char_array)
FROM q;
return collection of strings
WITH q AS
(SELECT LEVEL ID,
TRUNC(SYSDATE) + LEVEL MyDate,
to_char(LEVEL) STRING
FROM dual
CONNECT BY LEVEL < 5)
SELECT CAST(COLLECT(MyDate) AS date_array)
FROM q
return error invalid datatype.
Can anyone explain why the Date datatype behaves differently?
Here are my findings... it seems you are facing a bug caused by the fact that calculated dates seem to have a different internal representation from "database" dates. I did find a workaround, so keep on reading.
On my oracle dev installation (Oracle 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production) I am experiencing your same problem.
BUT... If I create a physical table containing your test data:
create table test_data as
SELECT LEVEL ID,
TRUNC(SYSDATE) + LEVEL MyDate,
to_char(LEVEL) STRING
FROM dual
CONNECT BY LEVEL < 5
and then run the "cast collect" operator on this physical table, it works as expected:
-- this one works perfectly
SELECT CAST(COLLECT(MyDate) AS date_array) from test_data
but all these examples still do NOT work:
-- here I just added 1 .. and it doesn't work
SELECT CAST(COLLECT(MyDate + 1) AS date_array)
from test_data
-- here I am extracting sysdate, instead of a physical column... and it doesn't work
SELECT CAST(COLLECT(sysdate) AS date_array)
from test_data
It feels like oracle doesn't think that calculated dates are the same thing of physical dates
So, I tried to "persuade" oracle that the data I am providing is actually a normal DATE value, using an explicit cast... and EUREKA! this does the job correctly:
WITH q AS
(SELECT LEVEL ID,
-- this apparently unnecessary cast does the trick
CAST( TRUNC(SYSDATE) + LEVEL AS DATE) MyDate,
to_char(LEVEL) STRING
FROM dual
CONNECT BY LEVEL < 5)
SELECT CAST(COLLECT(MyDate) AS date_array)
FROM q
Yes... but why??
It really seems that these two values are not exactly the same thing, even if the values we see are actually the same:
select sysdate, cast (sysdate as date) from dual
So I dug in the internal representation of the two values applying the "dump" function to both of them:
select dump(sysdate), dump(cast (sysdate as date)) from dual
and these are the results I got:
DUMP(SYSDATE ) -> Typ=13 Len=8: 226,7,11,9,19,20,47,0
DUMP(CAST(SYSDATEASDATE) as DUAL) -> Typ=12 Len=7: 120,118,11,9,20,21,48
Internally they look like two totally different data types! one is type 12 and the other is type 13... and they have different length and representation.
Anyway I discovered something more.. it seems someone else has noticed this: https://community.oracle.com/thread/4122627
The question has an answer pointing to this document: http://psoug.org/reference/datatypes.html
which contains a lengthy note about dates... an excerpt of it reads:
"What happened? Is the information above incorrect or does the DUMP()
function not handle DATE values? No, you have to look at the "Typ="
values to understand why we are seeing these results. ". The datatype
returned is 13 and not 12, the external DATE datatype. This occurs
because we rely on the TO_DATE function! External datatype 13 is an
internal c-structure whose length varies depending on how the
c-compiler represents the structure. Note that the "Len=" value is 8
and not 7. Type 13 is not a part of the published 3GL interfaces for
Oracle and is used for date calculations mainly within PL/SQL
operations. Note that the same result can be seen when DUMPing the
value SYSDATE."
Anyway, I repeat: I think this is a bug, but at least I found a workaround: use an explicit cast to DATE.

stddev function in plsql is giving me the wrong value

I need to calculate the stddev function in plsql, but when I compared the values with java program, it is different.
I need to get the stddev function for this set of values(100,104,105,103,110,115,130,95,91,105,106,101,65,91,95), when I used plsql the value is : 14.032 and using java it is 13.557. could you please help in getting the correct value using oracle plsql
Here is an explicit SQL query which takes your numbers and steps them through the Standard Deviation calculation.
with t23 as (
select column_value as val
from table (sys.odcinumberlist(100,104,105,103,110,115,130,95,91,105,106,101,65,91,95))
)
, mn as (
select avg(val) as avg_val
, count(*) as cnt
from t23
) , inp as (
select t23.val
, t23.val - mn.avg_val as diff
, power(t23.val - mn.avg_val , 2) diff_sq
, mn.cnt
from t23 cross join mn
)
select sum(diff_sq) as sum_diff_sq
, sqrt( sum(diff_sq) / (cnt-1) ) as sd
from inp
group by cnt
;
The value of SD is 14.0329544118054 which suggests the Oracle stddev() function is correct and whatever you're running in Java is incorrect.
Great code there #APC - I like the look through nature of the code :)
So I came across this same issue today and the answer is Oracle has two built-in functions for Standard Deviation according to the two distinct calculations:
a) stddev - for standard deviation sample; and
b) stddev_pop standard deviation population
select stddev(column_value), stddev_pop(column_value)
from table (sys.odcinumberlist(100,104,105,103,110,115,130,95,91,105,106,101,65,91,95))
Example
STDDEV(COLUMN_VALUE) STDDEV_POP(COLUMN_VALUE)
-------------------- ------------------------
14.0329544 13.5571219
So use the one that suits your needs...
Some info on standard deviations and which one to use here.

How to declare date parameter like Start_date,end_date in oracle ? and how to pass it?

My query is
select
'1' as KPI_ID, 'P2P' as KPI_DESC,'22-MAR-17' as dates,
(sum(case when S_DATE between add_months('22-MAR-17',0)-13
and add_months('22-MAR-17',0)-7 then VOLUME else 0 end )) LAST_WEEK_Volume,
(sum(case when S_DATE between add_months('22-MAR-17',0)-6
and add_months('22-MAR-17',0) then VOLUME else 0 end )) THIS_WEEK_Volume
from
table
problem statement -actually i have two years old data ..i want calculate last week volume,current week volume day wise for 2 years.so what should i modify in query .current query gives only 1 day calculation .i want to do per day wise calculation.according to google i found that after defining paramater start_date and end_date and passing to column it can be possible,could u help me out pleasr?
RTFM?
Oracle built-in function TO_DATE is what you need.
See Oracle documentation.
select TO_DATE(`14-FEB-2018`,`DD-MON-YYYY`) from DUAL
UPDATE
In reply to your comment...
Actually i am new in pl-sql
I suggest (again) RTFM.
Go to the Oracle Database Documentation Web page and select the appropriate Oracle database version.
Regarding PL/SQL, I suggest PL/SQL Language Reference
You could use substitution
define my_date = '''22-MAR-17''';
select
'1' as KPI_ID, 'P2P' as KPI_DESC, TO_DATE(&my_date,'DD-MON-YY') as dates,
(sum(case when S_DATE between add_months(TO_DATE(&my_date,'DD-MON-YY'),0)-13
and add_months(TO_DATE(&my_date,'DD-MON-YY'),0)-7 then VOLUME else 0 end )) LAST_WEEK_Volume,
(sum(case when S_DATE between add_months(TO_DATE(&my_date,'DD-MON-YY') ,0)-6
and add_months(TO_DATE(&my_date,'DD-MON-YY') ,0) then VOLUME else 0 end )) THIS_WEEK_Volume
from
table;
undefine my_date;

compare 13digit (millisecond) unix timestamp with date in oracle

A database column (VARCHAR2 datatype) stores the date/time as 13 digit (milliseconds
) unixtimestamp format. Now when I want to compare the column with a oracle date (in question), The error thrown as 'invalid number'
I tried both ways,
converting the 13digit number to Date and compare with the date in question like below. The expressions seems valid as they are printed in select query, but if i include in the where part, it throws 'invalid number'
Here 'value' is 13th digit unixtimestamp column of VARCHAR2 datatype.
select
TO_DATE('1970-01-01', 'YYYY-MM-DD') + value/86400000,
TO_DATE('2014-04-21', 'YYYY-MM-DD')
from dummytable
-- where and TO_DATE('1970-01-01', 'YYYY-MM-DD') + value/86400000 > TO_DATE('2014-04-21', 'YYYY-MM-DD')
converting the date in question to 13digit unixtimestamp and comparing with the database column.The expressions seems valid as they are printed in select query, but if i include in the where part, it throws 'invalid number'
.
select
value,
(to_date('2013-04-21', 'YYYY-MM-DD') - to_date('1970-01-01', 'YYYY-MM-DD')) * (1000*24*60*60)
from dummytable
-- where value > ((to_date('2013-04-21', 'YYYY-MM-DD') - to_date('1970-01-01', 'YYYY-MM-DD')) * (1000*24*60*60))
any pointers? Thanks in advance.
[EDIT- 1 day later] I see the problem now. There are some data (other rows) for the 'value' column that are non-numeric. But I have another column say field, where always field='date' return value as 13 digit timestamp. Now I think when 'where' condition executes, although the field='date' is in the condition, it is still validating the other values for 'value' which are non-numeric. Is there a way to avoid this ?
Your code works just fine. The problem is in your data. Some of your values is not a number.
create table test
(value varchar2(13));
insert into test(value) values('2154534689000');
--insert into test(value) values('2 54534689000');
select TO_DATE('1970-01-01', 'YYYY-MM-DD') + value/86400000
from test
where TO_DATE('1970-01-01', 'YYYY-MM-DD') + value/86400000 > TO_DATE('2014-04-21', 'YYYY-MM-DD');
This code works fine. But if you uncommented the second insert, you would get exactly the same invalid number error as you get.
UPD. Allan gave you a nice hint, but i feel that it can be good to explain you a bit about views. The fact that you select from a view CAN make a difference. A view is not stored somewhere physically, when you select from it, it is just "added to your query". And then Oracle Query Optimizer starts working. Among other things, it can change the order in which your where predicates are evaluated.
For example, your the view query can have a line where value is not null and it would normally show only 'good' values. But if your query has a predicate where to_date(value,'ddmmyyyy') > sysdate, Oracle can decide to evaluate your predicate earlier, because Oracle predicts that it would "cut off" more rows, thus making the whole query faster and less momery consuming. Of course, execution will crash because of an attempt to convert a null string to date.
I believe, that Allan in his answer that he gave a link to, gave a great way to solve this problem: "wrapping" your query in a subquery that Oracle can't "unwrap":
select value
from
(select value
from my_view
where rownum > 0)
where to_date(value,'ddmmyyyy') > sysdate
Hope that helps.

Resources