Range of values in set statement in Hive - hadoop

Is it possible to enter a range of values in the set statement in Hive:
eg:
PROC FORMAT;
VALUE $ABCD
'3000',
'3001',
'8816' - '8820',
'1517' - '1599' = 'Y'
OTHER = 'N';
I need this format statement in SAS to be converted and I have entered the values in set statement of Hive so I can use the 'ABCD' value in a case statement later. I am unable to find a way out to write out the range of values.
I cannot just list them out since they are not necessarily whole numbers.

It is not just a syntax translation.
If you are working with SQL, you have to think SQL.
It seems you are looking for something similar to -
case
when mycol in (3000, 3001)
or mycol between 8816 and 8820
or mycol between 1517 and 1599
then 'Y'
else 'N'
end

Related

convert TO_CHAR, IS_DATE to hive query

I want to convert specific data to Hive.
However, functions available in Oracle cannot be used in Hive. How can I solve this?
The applied conversion rule is as follows.
DECODE(TRUE, IS_DATE(TO_CHAR(columnname , 'YYYYMMDD')), 'YYYYMMDD',NULL)
In the case of DECODE, it was confirmed that it could be processed with IF.
But I couldn't find a way to change IS_DATE function and TO_CHAR function.
Oracle does not have an IS_DATE function. Are you sure this is not a user-defined function? If so then you will need to look at the source code and check what it does and duplicate that in Hive.
DECODE(a, b, c, d) can be rewritten as a CASE expression:
CASE WHEN a = b THEN c ELSE d END
So your code (assuming that columnname is a DATE and you are using TO_CHAR to convert it to a string and then IS_DATE checks if it is a valid date, which seems pointless as it will only not be a valid date when columnname is NULL) would convert to:
CASE
WHEN CAST(columnname AS STRING FORMAT 'YYYYMMDD') IS NOT NULL
THEN 'YYYYMMDD'
ELSE NULL
END
or, more simply:
CASE
WHEN columnname IS NOT NULL
THEN 'YYYYMMDD'
ELSE NULL
END

How do I get N rows in Oracle SQL SELECT statement given number by variable?

In Oracle SQL, I have a variable that is the number of rows to fetch, I can only use SQL SELECT statement, so no PL/SQL block.
If the variable has a value set I must fetch the number of rows in the variable, if not then fetch as many rows as possible (infinite).
I tried:
select * from system_options
THEN FETCH FIRST
CASE :lim
THEN :lim
ELSE 9999
END
ROWS ONLY
This gives me a ORA-00933: SQL command not properly ended.
Another option would be by not having the variable set then not having the THEN FETCH statement.
You have several syntax errors:
You do not need the THEN before the FETCH FIRST; and
The CASE expression is missing a WHEN clause.
I don't have SQL/Plus to hand to test using a bind variable but something like this:
select * from system_options
FETCH FIRST CASE WHEN :lim IS NOT NULL THEN :lim ELSE 9999 END ROWS ONLY
Or, you can use COALESCE:
select * from system_options
FETCH FIRST COALESCE( :lim, 9999 ) ROWS ONLY
db<>fiddle here

Make condition only if "something" - Query Oracle

i'm with a problem in a query.
I have a table called "store" that I need to query.
Select s.store_name
from store s
where s.store = case
when p_store != 0 then
p_store
else
s.store
end;
This should work but as I have "stores" with characters (-) in column and this is defined as number, that query raise an exception: ORA-01722: invalid number.
So I want to do something like this in query:
IF p_store != 0 then
select store_name from store where store = p_store
else
select store_name from store;
Is it possible?
Thanks!
EDIT:
The query that I wrote above was an example of the query I was running.
The exception was raised because another column (too much hours in front of PC :-( ).
This table have a column that's varchar2(15) and I was doing this condition:
(...)AND S.CODE > 4 (...)
The correct condition that I want to do is:
(...)AND LENGTH(S.CODE) > 4
Thank you all!
As far as I understand you have varchar2 s.store which in fact contains numbers so Oracle tries to compare it casting to numbers but at some point it gets - and throws an exception. What you should do is update on table replacing - by null. But if you don't want to do that you can try to make case return varchar2
Select s.store_name
from store s
where s.store = case
when to_char(p_store) != '0' then
to_char(p_store)
else
s.store
end;
I am guessing you are running the query in a plsql block (as cursor?). In that case dynamic sql is the way to go. check out REF CURSOR too (google!).

oracle produce different result for two same queries when only change field,value

I have SQL query . When I declare variable and run the query it produce 39 rows but when I use a literal value instead of variable and run query it produce three rows. How can it be ?
Here is query and results with variables
declare
fromnode number :=1;
CURRENTESTIMATE number :=0;
begin
for ts in (SELECT e.fromnode,e.tonode,e.weight
FROM TS_DIJNODEESTIMATE N
INNER JOIN TS_EDGE E ON N.ID=E.TONODE
WHERE N.DONE=0 AND E.FROMNODE=fromnode AND (CURRENTESTIMATE+E.WEIGHT)<N.ESTIMATE)
loop
dbms_output.put_line(ts.fromnode || ',' || ts.tonode || ',' || ts.weight);
end loop;
end;
The result is
1,2,1306
1,5,2161
1,6,2661
2,3,919
2,4,629
3,2,919
3,4,435
3,5,1225
3,7,1983
4,2,629
4,3,435
5,3,1225
5,6,1483
5,7,1258
6,5,1483
6,7,1532
6,8,661
7,3,1983
7,5,1258
7,6,1532
7,9,2113
7,12,2161
8,6,661
8,9,1145
8,10,1613
9,7,2113
9,8,1145
9,10,725
9,11,383
9,12,1709
10,8,1613
10,9,725
10,11,338
11,9,383
11,10,338
11,12,2145
12,7,2161
12,9,1709
12,11,2145
With literal instead of variable:
declare
fromnode number :=1;
CURRENTESTIMATE number :=0;
begin
for ts in (SELECT e.fromnode,e.tonode,e.weight
FROM TS_DIJNODEESTIMATE N
INNER JOIN TS_EDGE E ON N.ID=E.TONODE
WHERE N.DONE=0 AND E.FROMNODE=1 AND (0+E.WEIGHT)<N.ESTIMATE)
loop
dbms_output.put_line(ts.fromnode || ',' || ts.tonode || ',' || ts.weight);
end loop;
end;
the result is
1,2,1306
1,5,2161
1,6,2661
The desired result is the second result.
You should change the name of your variable fromnode to my_fromnode or something like that.
In your firt query inside where the E.FROMNODE=fromnode is actually comparing the column with itself and returns true.
The problem is naming: you gave your variable the same name as the table column:
E.FROMNODE=fromnode
Oracle's scoping rules resolve names using the nearest match, starting from the innermost point, working outwards and upwards. The nearest namespace in a query is the table so it first attempts to resolve fromnode as a table column. The name fits, so the compiler doesn't look any further.
Effectively your WHERE clause filter is logically the same as 1 = 1, and that's why you get more rows. This should not be a surprise as it is the documented behaviour. The PL/SQL documentation covers scope of variable identifier names here and the interaction with variable names here. The key point is the one Alex Poole highlights:
"If a SQL statement references a name that belongs to both a column and either a local variable or formal parameter, then the column name takes precedence."
You thought you had avoided this by putting fromnode in lower case but PL/SQL is not case sensitive. The correct approach is to use a naming convention such as identifying variables with a prefix: V for variable - v_fromnode - or L for Local - l_fromnode - are both common conventions.

Oracle cursor returning all rows in table despite where clause

I am using the following query to return a single value:
select er.elig_code
from idm_elig_rule er
where ER.ROLE_CODE = role_code and ER.SERVICE_CODE = service_code;
When I substitute values for the variables and run it as a single SQL statement it will return just a single value like I want it too. However, when I place the statement in a cursor and loop through the results, it returns all rows in the table. I've also tried a "select into" statement but that still returns all 85 rows in the table. I have a unique index in the idm_elig_rule table that is a combination of the role_code, service_code and another column.
EDIT: Here's how I'm testing it out - using an anonymous block:
declare
role_code_in IDM_ELIG_RULE.ROLE_CODE%type := 'CEMP';
service_code_in IDM_ELIG_RULE.SERVICE_CODE%type := 'PORTL';
cursor get_elig_code is
select ER.ELIG_CODE
from idm_elig_rule er
where ER.ROLE_CODE = role_code_in and ER.SERVICE_CODE = service_code_in;
begin
for r in get_elig_code
loop
DBMS_OUTPUT.PUT_LINE(r.elig_code);
end loop;
end;
EDIT: I changed the names of the variables in the where clause and that resolved the issue.
You have a Name Resolution issue with your variable names since the bind variable names are the same as the column names. Change your variable names to avoid the PL/SQL compiler from deciding for you.
Oracle PL/SQL Variable Name Resolution
Since your variable names are the same as the column names, it is possible that the parser is seeing them as the column names, not as variable, and therefore you are getting all the rows where the columns are equal to themselves, which would only exclude rows with NULL values.
I'd suggest always using different names for your variables than for the columns, to avoid any confusion. A common technique is to use some prefix on the variable name, such as l_ for local variable, p_ for parameters, or g_ for globals.
In this case, it may be better to parameterize the cursor:
CURSOR code_cur (p_role_code INTEGER, p_service_code INTEGER) IS
select er.elig_code
from idm_elig_rule er
where ER.ROLE_CODE = p_role_code and ER.SERVICE_CODE = p_service_code;
Then you would pass values when opening the cursor, e.g.:
FOR code_rec IN code_cur ( my_role_code_value, my_service_code_value ) LOOP
From the limited information in your question i'd say that your parameters are not being instantiated correctly and your select is resolving to:
select er.elig_code
from idm_elig_rule er
where ER.ROLE_CODE = role_code
and ER.SERVICE_CODE = service_code;
Where the DB is seeing role_code and service_code as the columns and not variables so it will always return all rows from your table.
Change the names of your variables to something different from your column names to see if this is the case.

Resources