Consider the following code:
Select FLAGS,
CASE FLAGS
WHEN 0 THEN "10000000"
WHEN 1 THEN "01000000"
WHEN 2 THEN "00100000"
WHEN 3 THEN "00010000"
WHEN 4 THEN "00001000"
WHEN 5 THEN "00000100"
WHEN 6 THEN "00000010"
WHEN 7 THEN "00000001"
ELSE "00000000"
END AS Test-W
FROM V_TEST
The above statement is throwing error as:
ORA-00923: FROM keyword not found where expected
00923. 00000 - "FROM keyword not found where expected"
*Cause:
*Action: Error at Line: 14 Column: 17
My table name is V_TEST, column name is FLAGS. What am I doing wrong here?
use single quote ` for the literal expressions
The column Test-W needs to be enclosed in dobule quote
Select FLAGS,
CASE FLAGS
WHEN 0 THEN '10000000'
WHEN 1 THEN '01000000'
WHEN 2 THEN '00100000'
WHEN 3 THEN '00010000'
WHEN 4 THEN '00001000'
WHEN 5 THEN '00000100'
WHEN 6 THEN '00000010'
WHEN 7 THEN '00000001'
ELSE '00000000'
END as "Test-W"
FROM V_TEST
Of course, CASE is verbose and easy to interpret. You could also write the same query using DECODE -
SELECT FLAGS,
DECODE(FLAGS,
0 , '10000000',
1 , '01000000',
2 , '00100000',
3 , '00010000',
4 , '00001000',
5 , '00000100',
6 , '00000010',
7 , '00000001',
'00000000')
AS TEST-W
FROM V_TEST
/
Related
Hi I'm trying to compare two VARCHAR2 variables - new_value, old_value. I'm using Replace() to check the if there are common values and removing them from the new_value. The problem arises when:
old value = Test 1
Test 2
new_value = Test 1
Test 2
Char(10)
In this case the Replace() will remove all the values except the new line. I need way to check if only new line characters and/or spaces are there in the variable.
You can use the ASCII function to get the ASCII value of remaining data after replace and then easily check if it is space or newline as follows:
SQL> SELECT ASCII(REPLACE(N,O)) FROM
2 (SELECT
3 'Test 1
4 Test 2' AS O,
5 'Test 1
6 Test 2'
7 || CHR(10) AS N
8 FROM
9 DUAL);
ASCII(REPLACE(N,O))
-------------------
10 -- it means, it is new line
SQL>
In Oracle DB, have a table called Details. The Details table data shown below.
Name | Age
--------------
xxx | 4
yyy | 1
zzz | 10
Required to swap ages from 4 to 1 & 1 to 4 without disturbing age 10. I used below query which yields error in Oracle sql developer.
update details set age= case when age=4 then 1
when age=1 then 4 end;
tried below query also:
update details set age= case when age=4 then 1
when age=1 then 4
else null end;
Error report for both queries:
SQL Error: ORA-01407: cannot update ("DETAILS"."AGE") to NULL
01407.
*Cause:
*Action:
You can restrict the update just for rows with age 1 or 4
update details
set age= case
when age=4 then 1
when age=1 then 4
end
where age in (1,4)
This will work as well but you will do unnecessary updates
update details
set age= case
when age=4 then 1
when age=1 then 4
else age
end
COUNTNUM is a column name in a table that has data like below
1,2,3,4,
I used
RTRIM((COUNTNUM),',') COUNTNUM
It didn't work
Desired output
1,2,3,4
Current output
1,2,3,4,
Any suggestions would greatly help..!
Thanks
REGEXP_REPLACE((countnum), ',$', '')
Perhaps There are non-digits after the comma which needed to be removed
Logic is added to account for possible non-digits between the comma and the end of countnum.
Explanation:
[^[:digit:]] is the negation of the digit character class
* is a quantifier meaning zero to many
$ is an anchor identify the end of countnum
SCOTT#dev>WITH d AS (
2 SELECT
3 '1,2,3,4, ' countnum
4 FROM
5 dual
6 UNION ALL
7 SELECT
8 '1,2,3,4,'
9 FROM
10 dual
11 ) SELECT
12 countnum,
13 regexp_replace(
14 countnum,
15 ',[^[:digit:]]*$'
16 ) mod_count_num
17 FROM
18 d;
COUNTNUM MOD_COUNT_NUM
1,2,3,4, 1,2,3,4
1,2,3,4, 1,2,3,4
I'm trying to build a small blog allowing people to add comments..
For comments I prepared a table like this:
ID PostID ParentID Date Title Text User ....
1 1 0
2 2 0
3 1 0
4 1 1
5 1 1
6 1 4
7 1 1
8 1 5
9 1 8
where if ParentID is not 0 means that this comment is not referred to the post but to the comment with that ID (is nested)
ie: assuming to select Post 1 will extract all comments except ID=2.
we have posts 1 and 2 on the root
posts 4,5,7 are nested in comment 1
post 6 is nested in 4 (triple nesting)
post 8 is nested in 5 (triple nesting)
post 9 is nested in 8 (quadruple nesting)
Therefore I expect the query returns the record in this order:
1
4
6
5
8
9
7
2
But I'm struggling with the query to achieve the above result.
Actually, for single nesting I find a solution, but for deeper nesting.. have really no idea..
I also thought that table schema used is not adequate..
On the other side I thought that such issue can be a common issue, but google didn't gave me any valuable result.. probably used wrong keywords..
Can you please suggest a path to solve this problem, or where to search for?
Thanks!
Jan
the solution is in Eric Weilinau's answer at this Post.
Basically it uses a recurring CTE
I modified a little to use ID value as Order and adding a further filter.
Here is the query:
WITH [NodeList] (
[Id], [ParentId], [Level], [Order]
) AS (
SELECT [Node].[Id]
, [Node].[ParentId]
, 0 AS [Level]
, Right('0000'+CONVERT([varchar](MAX), [Node].[ID]),4) AS [Order]
FROM [Node]
WHERE [Node].[ParentId] = 0
UNION ALL
SELECT [Node].[Id]
, [Node].[ParentId]
, [NodeList].[Level] + 1 AS [Level]
, [NodeList].[Order] + '|'
+ Right('0000' + CONVERT([varchar](MAX), [Node].[ID]),4) AS [Order]
FROM [Node]
INNER JOIN [NodeList] ON [NodeList].[Id] = [Node].[ParentId]
) SELECT [NodeList].[id],
[NodeList].[Level],
REPLICATE('-', [NodeList].[Level] * 4) + [Node].[Name] AS [Name]
FROM [Node]
INNER JOIN [NodeList] ON [NodeList].[Id] = [Node].[Id]
WHERE BlogID=1
ORDER BY [NodeList].[Order]
if somebody can find it helpful.
Oracle behaves really extrange with the next query:
I am trying to evaluate these three records, one of them should show the column digitado = 1 because it accomplishes all the conditions, which are, NUM_DOCUMENTO_ENCABEZADO iS NOT NULL and ORIGEN_PLANILLA = 2
NUM_DOCUMENTO NUM_DOCUMENTO_ENCABEZADO ORIGEN_PLANILLA
8220568059 8220568059 2
8220681644 2
940723593097 1
select x.num_documento,
x.origen_planilla,
x.num_documento_encabezado,
case
when x.num_documento_encabezado > '0' and x.origen_planilla = 2 then
1
else
0
end digitado
from (
select h.num_documento,
h.num_documento_encabezado,
h.origen_planilla
from (
select a.num_documento,
c.num_documento num_documento_encabezado,
case when NVl(UPPER(a.txt_observacion),'X') like '%SGP%' THEN 1 ELSE 2 END origen_planilla
from epsis.ryc_recaudo a,
epsis.ryc_recaudo_unificado b,
epsis.ryc_documento_encabezado c
where a.fec_pago >= to_date('28082013','ddmmyyyy') ---aca se coloca el dia del ultimo proceso,
and a.fec_pago < to_date('25092013','ddmmyyyy')-- el cecaudo viene un dia atrasados
and b.num_documento(+) = a.num_documento
and c.num_documento(+) = b.num_documento --80595
and a.num_documento in ( '940723593097', '8220681644','8220568059')
) h,
epsis.ryc_divide_documento f,
epsis.ryc_documento_encabezado g
where f.num_documento(+) = h.num_documento
and g.num_documento(+) =f.num_division
group by h.num_documento,
h.num_documento_encabezado,
h.origen_planilla
) x
This is the result:
NUM_DOCUMENTO ORIGEN_PLANILLA NUM_DOCUMENTO_ENCABEZADO DIGITADO
8220568059 2 8220568059 0
8220681644 2 0
940723593097 1 0
The column DIGITADO should be "1" for the first record.
Oracle can not evaluate this "CASE" properly:
case
when x.num_documento_encabezado > '0' and x.origen_planilla = 2 then
1
else
0
end digitado
I have tried diferent things, for example if I change the previous code for this:
case
when length(x.num_documento_encabezado||x.origen_planilla) > 1 then
1
else
0
end digitado
This is the result:
NUM_DOCUMENTO ORIGEN_PLANILLA NUM_DOCUMENTO_ENCABEZADO DIGITADO
8220568059 2 8220568059 1
8220681644 2 0
940723593097 1 0
It works for every record, but that is not the point, the point is that oracle is not able to evaluate the "AND" expression, and the ortiginal query is much longer than the example displayed.
Now, another extrange this is that, when I execute the query only for the record that is ok, I mean this
and a.num_documento in ('8220568059')
the "AND" expression in the case sentence works properly with the original "CASE".
Result:
NUM_DOCUMENTO ORIGEN_PLANILLA NUM_DOCUMENTO_ENCABEZADO DIGITADO
8220568059 2 8220568059 1
Another thing is that, and here is where i believe the problem is, when no outer join in the second subquery, then the query runs ok, but I need that outer join, I am talking about this:
where f.num_documento(+) = h.num_documento
and g.num_documento(+) =f.num_division
I really don't want to rewrite the full query, does anyone know why this happen?
Create and insert statements, these ones reproduce the issue
create table tmp_origin
(
doc varchar2(30),
val number,
obs varchar2(30)
);
create table tmp_uni
(
doc varchar2(30),
doc_origin varchar2(30)
);
create table tmp_div
(
doc varchar2(30),
doc_div varchar2(30)
);
insert into tmp_origin values ('8220568059',100000, 'NORMAL');
insert into tmp_origin values ('8220681644',200000, 'NORMAL');
insert into tmp_origin values ('940723593097',300000, 'SGP');
commit;
insert into tmp_uni values ('8220568059','8220568059');
commit;
This is the query adapted to the above lines, I have also added some others cases, so you can compare and identify that the first one is not working
select x.num_documento,
x.origen_planilla,
x.num_documento_encabezado,
case
when x.num_documento_encabezado is not null and x.origen_planilla = 2 then
1
else
0
end digitado,
case
when length(x.num_documento_encabezado||x.origen_planilla) > 1 then
1
else
0
end digitado2,
case
when x.origen_planilla = 2 then
case
when x.num_documento_encabezado is not null then
1
else
0
end
else
0
end digitado3
from (
select h.num_documento,
h.num_documento_encabezado,
h.origen_planilla
from (
select a.doc num_documento,
b.doc num_documento_encabezado,
case when NVl(UPPER(a.obs),'X') like '%SGP%' THEN 1 ELSE 2 END origen_planilla
from tmp_origin a,
tmp_uni b
where a.doc in ( '940723593097', '8220681644','8220568059')
and b.doc(+) = a.doc
) h,
tmp_div f
where f.doc(+) = h.num_documento
group by h.num_documento,
h.num_documento_encabezado,
h.origen_planilla
) x
You should almost never use the comparison operators with VARCHAR2, it is almost never useful (except if you are writing a sorting algorithm). In your case especially, it doesn't do what you expect.
When you compare VARCHAR2s, the result will depend upon character ordering (for instance '2' is "greater" than '10' because 2 comes after 1 in the character table).
Consider:
SQL> select * from dual where '8220568059' > '0';
DUMMY
-----
X
SQL> select * from dual where ' 8220568059' > '0';
DUMMY
-----
Always use the right datatype for the right task. There is almost always only one datatype that will work correctly. You should always use NUMBER and explicit datatype conversion when working with numbers:
SQL> select * from dual where to_number('8220568059') > 0;
DUMMY
-----
X
Also if you just want to know if a value is NULL, please use the IS NOT NULL operator:
SQL> WITH DATA AS (
2 SELECT '8220568059' num_documento_encabezado,
3 2 origen_planilla FROM dual UNION ALL
4 SELECT '', 2 FROM dual UNION ALL
5 SELECT '', 1 FROM dual)
6 SELECT x.origen_planilla,
7 x.num_documento_encabezado,
8 CASE
9 WHEN x.num_documento_encabezado IS NOT NULL
10 AND x.origen_planilla = 2 THEN
11 1
12 ELSE
13 0
14 END digitado
15 FROM DATA x;
ORIGEN_PLANILLA NUM_DOCUMENTO_ENCABEZADO DIGITADO
--------------- ------------------------ ----------
2 8220568059 1
2 0
1 0