I need to convert a number to another value based on a range:
ie:
7 = "A"
106 = "I"
I have a range like this:
from to return-val
1 17 A
17 35 B
35 38 C
38 56 D
56 72 E
72 88 F
88 98 G
98 104 H
104 115 I
115 120 J
120 123 K
123 129 L
129 infinity M
The values are fixed and do not change.
I was thinking a lookup table would be required, but is there a way it could be done with a function on an analytics function inside of oracle?
Think I would use a mapping table:
mapping:
to ret
17 A
38 B
Select Max(ret)
From mapping
Where x <= to
You could also use CASE WHEN:
Select Case When x <= 17 Then 'A'
When x <= 35 Then 'B'
When x <= 38 Then 'C'
...
Else 'M' End
From your_table
SQL servers are designed such that operating on a table is faster than anything else -- particularly when that table will only have 13 rows.
I would create a function, in oracle, since it should be more efficient than doing a table lookup (no roundtrip to disk will ever be involved).
CREATE OR REPLACE Function ValueFromRange
( n IN number )
RETURN varchar2
IS
ret varchar2;
BEGIN
ret := -1; -- UNDEFINED?
IF n >= 1 and n <= 17 THEN
ret := 'A';
ELSIF n >= 18 and n <= 35 THEN
ret := 'B';
ELSIF n >= 36 and n <= 38 THEN
ret := 'C';
ELSIF n >= 39 and n <= 56 THEN
ret := 'D';
ELSIF n >= 57 and n <= 72 THEN
ret := 'E';
ELSIF n >= 73 and n <= 88 THEN
ret := 'F';
ELSIF n >= 89 and n <= 98 THEN
ret := 'G';
ELSIF n >= 99 and n <= 104 THEN
ret := 'H';
ELSIF n >= 105 and n <= 115 THEN
ret := 'I';
ELSIF n >= 116 and n <= 120 THEN
ret := 'J';
ELSIF n >= 121 and n <= 123 THEN
ret := 'K';
ELSIF n >= 124 and n <= 129 THEN
ret := 'L';
ELSIF n >= 130 THEN
ret := 'M';
END IF;
RETURN ret;
END;
Related
I cant compile this PL/SQL stored function successfully. Cant find a right way to do it..
CREATE OR REPLACE FUNCTION calGrade
(
cmark IN student.mark%TYPE
)
RETURN VARCHAR2
IS
comment VARCHAR2(10);
BEGIN
IF cmark := 1 THEN comment := 'Very Poor';
ELSIF cmark := 2 THEN comment := 'Poor';
ELSIF cmark := 3 THEN comment := 'Moderate';
ELSIF cmark := 4 THEN comment := 'Good';
ELSIF cmark := 5 THEN comment := 'Excellent';
END IF;
RETURN comment;
END;
/
Remove colon from all IFs.
SQL> CREATE OR REPLACE FUNCTION calGrade (cmark IN student.mark%TYPE)
2 RETURN VARCHAR2
3 IS
4 comment VARCHAR2 (10);
5 BEGIN
6 IF cmark = 1
7 THEN
8 comment := 'Very Poor';
9 ELSIF cmark = 2
10 THEN
11 comment := 'Poor';
12 ELSIF cmark = 3
13 THEN
14 comment := 'Moderate';
15 ELSIF cmark = 4
16 THEN
17 comment := 'Good';
18 ELSIF cmark = 5
19 THEN
20 comment := 'Excellent';
21 END IF;
22
23 RETURN comment;
24 END;
25 /
Function created.
SQL>
How about using a case expression instead?
comment := (CASE cmark
WHEN 1 THEN 'Very Poor'
WHEN 2 THEN 'Poor'
WHEN 3 THEN 'Moderate'
WHEN 4 THEN 'Good'
WHEN 5 THEN 'Excellent'
END);
SQL> DECLARE
2 SEL NUMBER(3);
3 ans VARCHAR(20);
4 BEGIN:
5 SEL := &SEL ;
6 CASE SEL
7 WHEN 1 THEN ans := 'SUNDAY';
8 WHEN 2 THEN ans := 'MONDAY';
9 WHEN 3 THEN ans := 'TUESDAY';
10 WHEN 4 THEN ans := 'WEDNESDAY';
11 WHEN 5 THEN ans := 'THURSDAY';
12 WHEN 6 THEN ans := 'FRIDAY';
13 WHEN 7 THEN ans := 'SATURDAY';
14
15 END CASE;
16 DBMS_OUTPUT.PUT_LINE(' CORRESPONDING DAY FOR THE NUMBER '||SEL||' IS '||DAY);
17 END;
18 /
Enter value for sel: 3
old 5: SEL := &SEL ;
new 5: SEL := 3 ;
SP2-0552: Bind variable "SEL" not declared.
There are two problems in your block:
There is a colon after BEGIN, it's not supposed to be there
In your output there is a the DAY variable that is not declared, it should be the variable ans.
Below is the working version:
DECLARE
SEL NUMBER(3);
ans VARCHAR(20);
BEGIN
SEL := &SEL ;
CASE SEL
WHEN 1 THEN ans := 'SUNDAY';
WHEN 2 THEN ans := 'MONDAY';
WHEN 3 THEN ans := 'TUESDAY';
WHEN 4 THEN ans := 'WEDNESDAY';
WHEN 5 THEN ans := 'THURSDAY';
WHEN 6 THEN ans := 'FRIDAY';
WHEN 7 THEN ans := 'SATURDAY';
END CASE;
DBMS_OUTPUT.PUT_LINE(' CORRESPONDING DAY FOR THE NUMBER '||SEL||' IS '||ans);
END;
/
I had generate 1 round numbers:
set serveroutput on
declare
i number(9);
x number(9) := 0;
begin
for i in 0..7 loop
DBMS_OUTPUT.PUT_LINE(x);
x:=x+1;
end loop;
end;
Result is: 0, 1, 2, 3....7
My next round should generate numbers: 10, 11, 12....17
Total output should looks as below:
0 1 2 3 4 5 6 7
10 11 12 13 14 15 16 17
20 21 22 23 24 25 26 27
...
80 81 82 83 84 85 86 87
How can I jump 3 between each round? I will increase my counter till 81.
set serveroutput on
declare
i number(9);
y number(9);
x number(9) := 0;
z number(9) := 0;
begin
for y in 0..8 loop
for i in 0..7 loop
DBMS_OUTPUT.PUT_LINE(x);
x := z+i+1;
end loop;
z := z + 10;
x := z;
end loop;
end;
Looks like you want to output 9 times 7 numbers. That is one loop running 9 times and inside a loop that runs 7 times, I'd say. E.g.
begin
for i in 0..8 loop
for j in 0..7 loop
dbms_output.put(i * 10 + j);
dbms_output.put(' ');
end loop;
dbms_output.put_line('');
end loop;
end;
How about such a WHILE loop?
SQL> set serveroutput on
SQL> declare
2 i number := 0;
3 begin
4 while i < 30
5 loop
6 dbms_output.put_line (i);
7
8 i := i + case when substr (to_char (i), -1) >= 7 then 3 else 1 end;
9 end loop;
10 end;
11 /
0
1
2
3
4
5
6
7
10
11
12
13
14
15
16
17
20
21
22
23
24
25
26
27
PL/SQL procedure successfully completed.
SQL>
The Logic is: if i mod 10 = 7 then increment by 3 otherwise increment by one. Thus,
set serveroutput on
declare
i number(9);
x number(9) := 0;
begin
for i in 0..100 loop
DBMS_OUTPUT.PUT_LINE(x);
IF mod(i,10) = 7 THEN
x := x +3;
ELSE
x:=x+1;
END IF;
end loop;
end;
I'm attempting to implement the following logic equation in Verilog:
A1'*B1 + A1'*A0'*B0 + A0'*B1*B0
where A1, A0, B1, B0 are inputs and ' indicates negation. This is my first go at coding in Verilog, and I'd like to see if I'm on the right track. Any help would be much appreciated.
This is what I have worked up:
1 module HW7P1( A1, A0, B1, B0, O )
2 input A1, A0, B1, B0
3 output reg O;
4
5 always #( A1 or A0 or B1 or B0 )
6 begin
7 if( !A1 && B1 ) begin
8 O <= 1;
9 end else if( !A1 && !A0 && B0 ) begin
10 O <= 1;
11 end else if( !A0 && B1 && B0 ) begin
12 O <= 1;
13 end else begin
14 O <= 0;
15 end
16 end
Have I done anything wrong here?
I believe the following continuous assignment is equivalent to your logic equation:
wire O = (!A1&B1) | (!A1&A0!&B0) | (!A0&B1&B0);
You should create a testbench to prove that this is the logic you desire.
Can any one provide an SQL function which input string and output the next incremental string as per the following sequence?
000000
000001
.
.
000009
00000A
.
.
00000Z
.
.
.
000010
000011
.
.
000019
00001A
.
.
zzzzzz
If you are able to use a PL/SQL function, you could try something like the function, next_step, in this block, which increments over an arbitrary numeral set.
DECLARE
i integer;
seqnum varchar2(20) := '00';
----------------------------------------
function next_step(seq_num varchar2) return varchar2 is
digits varchar2(20) := '012ABC';
last_digit varchar2(1) := substr(seq_num, length(seq_num), 1);
other_digits varchar2(20) := substr(seq_num, 1, length(seq_num) -1);
-- value of last digit
last_digit_value number(5) := instr(digits, last_digit) - 1;
BEGIN
if seq_num is null then
return substr(digits, 2, 1);
end if;
-- increment the digit; roll if needed.
last_digit_value := last_digit_value + 1;
-- "digits||digits" makes the roll easy.
last_digit := substr(digits||digits, last_digit_value + 1, 1);
if last_digit_value >= length(digits) then
-- roll over
other_digits := next_step(other_digits);
end if;
return other_digits||last_digit;
END next_step;
----------------------------------------
BEGIN
dbms_output.enable(null);
dbms_output.put_line(seqnum);
for i in 1 .. 50 loop
seqnum := next_step(seqnum);
dbms_output.put_line(' -> '||seqnum);
end loop;
END;
/
It yields the following:
00
-> 01
-> 02
-> 0A
-> 0B
-> 0C
-> 10
-> 11
-> 12
-> 1A
-> 1B
-> 1C
-> 20
-> 21
-> 22
...
-> C2
-> CA
-> CB
-> CC
-> 100
-> 101
-> 102
...
-> 121
-> 122