How to modify Oracle SQL query to Snowflake - oracle

Using Oracle SQL, there is a function, noted below, that will allow you to create a "list" of names, phone numbers, etc., without using
multiple DUAL queries and UNION/UNION ALL to get more than one record.
The query below produces a list in this case of 10 names.
SELECT COLUMN_VALUE USERNAME
FROM TABLE(SYS.DBMS_DEBUG_VC2COLL(
'WARNER,JEFF',
'MALITO,CARL',
'MOODY,JEANNE',
'PHILLIPS,HUGH & KELLY',
'PATSANTARAS,VICTORIA',
'BROWN,ROLAND',
'RADOSEVICH,MIKE',
'RIDER,JACK',
'MACLEOD,LENARD',
'SCOTT,DAN' ))
However, when trying to run this same query in Snowflake, it will not work.
I receive this error: SQL compilation error: Invalid identifier SYS.DBMS_DEBUG_VC2COLL
Is there a "Snowflake version" of this query that can be used?

Here are some options, you can see which works best for you.
This works if you can get your SQL to look similar:
SELECT $1::VARCHAR AS column_value
FROM (VALUES ('WARNER,JEFF'), ('MACLEOD,LENARD'), ('SCOTT,DAN'));
This also works if you can get your list to be in a single string, delimited by a pipe or similar:
SELECT value::VARCHAR AS column_value
FROM LATERAL FLATTEN(INPUT=>SPLIT('WARNER,JEFF|MACLEOD,LENARD|SCOTT,DAN', '|'));
If you have the strings in the format 'a','b' and find it painful to do one of the above, I'd do something like this:
SELECT value::VARCHAR AS column_value
FROM LATERAL FLATTEN(INPUT=>SPLIT(ARRAY_TO_STRING(ARRAY_CONSTRUCT('WARNER,JEFF', 'MALITO,CARL', 'MOODY,JEANNE'), '|'), '|'));
Similar to the above suggestions, you can try this:
SELECT VALUE::VARCHAR as column_name
FROM TABLE(FLATTEN(INPUT => ARRAY_CONSTRUCT('WARNER,JEFF', 'MALITO,CARL', 'MOODY,JEANNE'), MODE => 'array'));

Related

Vertica - Subquery used as an expression returned more than one row

Is it possible to run a query which matches ANY rows in another table column? I'm trying to run this for example:
SELECT *
FROM emails
WHERE address ILIKE '%#' || IN (select * from dictionary.wordlist) || '.%'
However this returns [Vertica]VJDBC ERROR: Subquery used as an expression returned more than one row
Now that's a strange way of formulating it...
If you go back to a basic SQL tutorial, you will understand that a string literal like '%#' , which can be the operand of an ILIKE predicate, cannot be concatenated with an IN () clause - which is a predicate in itself.
I assume that you are looking for all rows in the emails table whose address contains any of the words in dictionary.wordlist between the at-sign and a dot.
I hope (correct me if I'm wrong) that dictionary.wordlist is a table with one column in VARCHAR() or other string format. If that is the case, you can go like this:
WITH
-- out of "dictionary.wordlist", create an in-line-table containing a column
-- with the wildcard operand to be later used in an ILIKE predicate
operands(operand) AS (
SELECT
'%#'||wordlist.word||'.%'
FROM dictionary.wordlist
)
SELECT
emails.*
FROM emails
INNER JOIN operands
ON email.address ILIKE operands.operand
;
There are other ways of doing it, of course, but this is one of them.
I'm not trying to say it will be very fast - an ILIKE predicate as a JOIN condition can't be performant ...
Good luck
Marco the Sane

Getting error in vertica:For 'IN', types varchar and int are inconsistent DETAIL: Columns: unknown and unknown

I am trying to execute below query in vertica:
select case
when to_char(to_date('02-15-2017','mm-dd-yyyy'),'mm')in(1,2,3,4,5,6,7,8,9,10) then
(select to_char(add_months(trunc(to_date('02-15-2017','mm-dd-yyyy'),'year'),-2),'mm-dd-yyyy') from dual);
else
(select to_char(add_months(trunc(to_date('02-15-2017','mm-dd-yyyy'),'year'),10),'mm-dd-yyyy') from dual)
end ett from dual;
Query is getting expected results in oracle but in Vertica Getting error
:For 'IN', types varchar and int are inconsistent DETAIL: Columns:
unknown and unknown.
Expected Result is fiscal Start date as 1st Nov 2016.
The base problem is that you are comparing a string to a number in your IN() predicate. (TO_CHAR() with a list of numbers). While Oracle (which your used syntax suggests) often implicitly converts data types to make a comparison happen, Vertica, like most other more ANSI compliant databases, is much stricter.
And you could have written your statement in a more concise way:
You don't need the FROM dual clause in Vertica (even if it implicitly adds it internally)
You wouldn't even have to nest the SELECTS in Oracle; it's enough to SELECT the whole CASE expression.
You could formulate the date literals much easier, by using the ISO format and preceding that string with the DATE keyword.
So, in general, I'd have written it like so:
SELECT
CASE
WHEN MONTH(DATE '2017-02-15') <= 10
THEN TO_CHAR(ADD_MONTHS(TRUNC(DATE '2017-02-05','YEAR'), -2),'mm-dd-yyyy')
ELSE TO_CHAR(ADD_MONTHS(TRUNC(DATE '2017-02-05','YEAR'), 10),'mm-dd-yyyy')
END AS ett
;

birt sql dataset with parameters sql error

I have a birt dataset for a db2 query. My query works fine without parameters with the following query...
with params as (SELECT '2014-02-16' enddate,'1' locationid FROM sysibm.sysdummy1)
select
t.registerid
from (
select
...
FROM params, mytable sos
WHERE sos.locationid=params.locationid
AND sos.repositorytype ='xxx'
AND sos.repositoryaccountability='xxx'
AND sos.terminalid='xxx'
AND DATE(sos.balanceDate) between date(params.enddate)-6 DAY and date(params.enddate)
GROUP BY sos.terminalid,sos.balancedate,params.enddate) t
GROUP BY
t.registerid
WITH UR
But when I change the top line to ...
with params as (SELECT ? enddate,? locationid FROM sysibm.sysdummy1)
And make the two input paramters of string datatype I get db2 errors sqlcode -418. But i know that it is not my querty because my query works.
What is the right way for me to set up the parameters so there is no error?
thanks
I'm not familiar with DB2 programming, but on Oracle the ? works anywhere in the query.
Have you looked at http://publib.boulder.ibm.com/infocenter/dzichelp/v2r2/index.jsp?topic=%2Fcom.ibm.db2z9.doc.codes%2Fsrc%2Ftpc%2Fn418.htm?
Seems that on DB2 it's a bit more complicated and you should use "typed parameter markers".
The doc says:
Typed parameter marker
A parameter marker that is specified with its target data type. A typed parameter marker has the general form:
CAST(? AS data-type)
This invocation of a CAST specification is a "promise" that the data type of the parameter at run time will be of the data type that is specified or some data type that is assignable to the specified data type.
Apart from that, always assure that your date strings are in the format that the DB expects, and use explicit format masks in the date function, like this:
with params as (
SELECT cast (? as varchar(10)) enddate,
cast (? as varchar2(80)) locationid
FROM sysibm.sysdummy1
)
select
...
from params, ...
where ...
AND DATE(sos.balanceDate) between date(XXX(params.enddate))-6 DAY and date(XXX(params.enddate))
...
Unfortunately I cannot tell you how the XXX function should look on DB2.
On Oracle, an example would be
to_date('2014-02-18', 'YYYY-MM-DD')
On DB2, see Converting a string to a date in DB2
In addition to hvb answer, i see two options:
Option 1 you could use a DB2 stored procedure instead of a plain SQL query. Thus there won't be these limitations you face to, due to JDBC query parameters.
Option 2, we should be able to remove the first line of the query "with params as" and replace it with question marks within the query:
select
t.registerid
from (
select
sos.terminalid,sos.balancedate,max(sos.balanceDate) as maxdate
FROM params, mytable sos
WHERE sos.locationid=?
AND sos.repositorytype ='xxx'
AND sos.repositoryaccountability='xxx'
AND sos.terminalid='xxx'
AND DATE(sos.balanceDate) between date(?)-6 DAY and date(?)
GROUP BY sos.terminalid,sos.balancedate) t
GROUP BY
t.registerid
A minor drawback is, this time we need to declare 3 dataset parameters in BIRT instead of 2. More nasty, i removed params.endDate from "group by" and replaced it with "max(sos.balanceDate)" in select clause. This is very near but not strictly equivalent. If this is not acceptable in your context, a stored procedure might be the best option.

Oracle Select where NCLOB is Like some string

I have an Oracle table, and in this table I have a column of type NCLOB. I would like to perform a SELECT LIKE on it like so:
SELECT
*
FROM
T_WEB_TASK_IT
WHERE DBMS_LOB.substr( T_WEB_TASK_IT.ISSUE_DESCRIPTION , 32000, 1)
LIKE '%Turning on the%'
But it isn't working, I get an error saying:
String buffer too small
But I don't understand how can that be, cause I know for a fact that there aren't that many characters in that column for that particular record!
You can use DBMS_LOB.INSTR function to search for strings in the lob. Like this:
SELECT *
FROM T_WEB_TASK_IT
WHERE DBMS_LOB.INSTR( T_WEB_TASK_IT.ISSUE_DESCRIPTION , 'Turning on the') > 0
Apart from DBMS_LOB.INSTR, you could also use Regular Expressions:
SELECT *
FROM T_WEB_TASK_IT
WHERE regexp_like(issue_description, 'Turning on the')

using sys_context to match data string

I'm trying to use data in sys_context form to perform a match in a WHERE clause.
What I put into the context is ('53','89'), which is what is returned when I select against dual.
My where statement is: where to_char(location_id) in sys_context('my_ctx','valoc')
Since I'm not getting the expected response, I'm guessing that what I think Oracle should see is not actually what it sees, but I don't know how to "look" at what's passed to the processor from TOAD.
The original form was where location_id in sys_context('my_ctx','valoc') with (53,89) in valoc, but that didn't return anything either. I'm sensing there may be no answer to my problem.
The problem is that the resulting WHERE clause is equivalent to this:
where to_char(location_id) in '('53','89')'
(didn't double the inner apostrophes for clarity)
The database sees what's retrieved from context as a single value, not as a list of values.
You can use the CONNECT BY trick to achieve your goal:
SELECT 1
FROM dual
WHERE '53' IN ( -- replace '53' with TO_CHAR(location_id)
SELECT regexp_substr('53,89', '[0-9]*', 1, level) -- replace '53,89' with sys_context('my_ctx','valoc')
FROM dual
CONNECT BY regexp_substr('53,89', '[0-9]*', 1, level) IS NOT NULL -- replace '53,89' with sys_context('my_ctx','valoc')
);

Resources