Oracle complex query help required - oracle

Can anyone help me getting the output data from oracle database with below conditions.
1.data for each mobile number with last updated ( latest date ) to be copied to an output file.
Note -- there can be multiple entries for single mobile number with different date.
TABLE STRUCTURE AS BELOW.
SQL> desc jtoom.mnp_port_nos_prbt_view;
Name Null? Type
----------------------------------------- -------- ----------------------------
LSA VARCHAR2(144)
MSISDN VARCHAR2(144)
RECIPIENT VARCHAR2(144)
DONOR VARCHAR2(144)
LRN VARCHAR2(144)
DT_STAMP DATE

Something similar to this may work:
select column_name, max(dt_stamp) max_dt_stamp
from table_or_view
group by column_name

This should do the trick:
SELECT DISTINCT A.Column_Name, A.Dt_Stamp
FROM jtoom.mnp_port_nos_prbt_view A
WHERE A.Dt_Stamp = (SELECT Max(B.Dt_Stamp) FROM jtoom.mnp_port_nos_prbt_view B WHERE B.Column_Name = A.Column_Name)

Related

Oracle view to return single column from multiple select columns

query 1: I need to get the dept code from one table.
query 2: use that dept code to query another table which also has got another set of dept code. kind of one is to many, one dept referring to many depts.
NOTE: they don't have the same column name in two tables.
and the final result should be union of 1st query and 2nd query.
for eg: query 1 result : ECE
query 2 result : EEE, Mech, Comp. Sc.
I need the result to be ECE, EEE, Mech, Comp. Sc.
declare default_dept_Code varchar2(10);
begin
select dept_code into default_dept_Code from (select dept_code from
course_per WHERE student_no ='526765771');
dbms_output.put_line(default_dept_Code);
SELECT dept_code FROM course_per WHERE student_no ='526765771'
union all
select add_dept_code from addition_dept where dept_Code = default_dept_Code;
I'm unable to execute this query, it has got error. What are the other best ways I can handle it, I need to put this in a VIEW. I tried to create temp table and insert the select result into it, did not work. I'm a new bee to Oracle. I don't want to use cursor, if that is the only option I can go for it.
From what I understand you can write your query like this:
SELECT dept_code as code
FROM course_per
WHERE student_no ='526765771'
UNION ALL
SELECT add_dept_code as code
FROM addition_dept
WHERE dept_Code = (
SELECT dept_code
FROM course_per
WHERE student_no ='526765771');

Oracle: ORA-01722: invalid number

I have a query which works nice when I run it inside sqlplus:
SQL> SELECT T_0.ID AS ATTR_1_, T_0_0.ID AS ATTR_2_,
CASE WHEN ( T_0.ID=1 AND ( T_0_0.ID=3 OR T_0_1.ID='val_1') )
THEN 'val_1' ELSE 'val_2' END AS TXT, T_0_1.ID,
CASE WHEN T_0.ID='boo' THEN 'boo' END AS EXTRA_FIELD
FROM TEST_TABLE T_0
INNER JOIN TEST_TABLE_2 T_0_0 ON ( T_0_0.ATTR=T_0.ID )
INNER JOIN TEST_TABLE_3 T_0_1 ON ( T_0_1.ID = T_0_0.ID )
WHERE ( ( T_0.ID=1 AND T_0_0.ID=3 )
OR T_0_1.ID=2 OR T_0_0.TXT='val_2');
no rows selected
Although, it returns nothing, it still works and does not result in error. However, when I do the same thing in Python, using bindings, I get this error message:
cx_Oracle.DatabaseError: ORA-01722: invalid number
This is how my query looks in Python, before I do cursor.execute:
SELECT T_0.ID AS ATTR_1_, T_0_0.ID AS ATTR_2_,
CASE WHEN ( T_0.ID=:TXT_ AND ( T_0_0.ID=:TXT__ OR T_0_1.ID=:TXT___ ) )
THEN :TXT___ ELSE :TXT____ END AS TXT, T_0_1.ID,
CASE WHEN T_0.ID=:EXTRA_FIELD THEN :EXTRA_FIELD END AS EXTRA_FIELD
FROM TEST_TABLE T_0
INNER JOIN TEST_TABLE_2 T_0_0 ON ( T_0_0.ATTR=T_0.ID )
INNER JOIN TEST_TABLE_3 T_0_1 ON ( T_0_1.ID = T_0_0.ID )
WHERE ( ( T_0.ID=:ID AND T_0_0.ID=:ID_ )
OR T_0_1.ID=:ID__ OR T_0_0.TXT=:TXT )
The query is just a string double-quoted "SELECT ..." . And this is how the dictionary with binding variables looks like:
OrderedDict([('TXT_', 1), ('TXT__', 3), ('TXT___', 'val_1'),
('TXT____', 'val_2'), ('EXTRA_FIELD', 'boo'), ('ID', 1),
('ID_', 3), ('ID__', 2), ('TXT', 'val_2')])
So, as you can see I have a perfect dictionary - number values are just numbers without quotes, string values are just strings with single quotes. I know, you will ask about the schema of the tables. So, here its is:
SQL> SELECT COLUMN_NAME, DATA_TYPE FROM USER_TAB_COLUMNS WHERE
TABLE_NAME = 'TEST_TABLE';
COLUMN_NAME
------------------------------
DATA_TYPE
------------------------------
ID
NUMBER
SQL> SELECT COLUMN_NAME, DATA_TYPE FROM USER_TAB_COLUMNS WHERE
TABLE_NAME = 'TEST_TABLE_2';
COLUMN_NAME
------------------------------
DATA_TYPE
------------------------------
ATTR
NUMBER
ID
NUMBER
TXT
VARCHAR2
SQL> SELECT COLUMN_NAME, DATA_TYPE FROM USER_TAB_COLUMNS
WHERE TABLE_NAME = 'TEST_TABLE_3';
COLUMN_NAME
------------------------------
DATA_TYPE
------------------------------
ID
NUMBER
So, it seems like one and the same query works good in the console, but does not work when using Python. Why is that?
EDIT
And here is a proof - a screen of two console windows. In the first console I run the query in sqlplus, in the second console I print sql query and the dictionary, which is used for binding variables:
EDIT
Oh, it's even more interesting. I was able to reproduce this error in Oracle shell and it looks like Oracle 11c bug. So, look at this:
Please, pay attention to the fact that ID field has a NUMBER type. And then pay attention to these two screens:
In the screen above you can see that everything is ok. However, if we slightly change it by adding OR T_0_1.ID=2 to the WHERE part, then it breaks:
So, this problem is reproducible even in Oracle shell. You can do it, using the schema I provided above.
EDIT
I updated the topic of my question, because it has nothing to do with Python. The whole problem with Oracle itself.
EDIT
BTW. My last comment does not contradict to the beginning part of my investigation. The thing is, if I have some data in TEST_TABLE_3, then the query breaks. And if I delete data, then is starts working. Here is a big proof:
How can data affect correctness of the query??
On your last screen just below the last line of the statement you have
CASE WHEN ( T_O.ID=1 AND ( T_0_0.ID=3 OR T_0_1.ID='VAL_1') )
there's an asterisk (now it helps, but sometimes it could lead in the wrong direction) showing the place of the encountered issue
T_0_1.ID='VAL_1'
in your table ID column is of Number type. 'VAL_1' - is Varchar.
As the comparison rules state:
When comparing a character value with a numeric value, Oracle converts the character data to a numeric value.
see (https://docs.oracle.com/database/121/SQLRF/sql_elements002.htm#SQLRF00214)
when oracle encounters this it tries to cast your string to number - and you get the error
How can data affect correctness of the query??
When there's no data in the table - there's no record returned from the table, hence there's no need the check the value of the column for equality - this comparison is not executed and no error shown

construct to be used in a for loop

I have sample Data like:
Table empdata:
Name Desig Sal
-------------------------
john staff 26000
sen owner 50000
smith assistant 10000
i want to print each of the columns like
Current field value is : John
Current field value is : staff
Current field value is : 26000
Current field value is : sen
Current field value is : owner
Current field value is : 50000.. and so on
I am able to use cursor to fetch the emp data:
cursor c1 is
select name, desig, sal from empdata;
but i want to iterate over the columns too. I have shown 3 columns here, but there are atleast 30 columns in actual data, and i would like to print each of the field.
Please help.
Hi you can use this kind basic code.
begin
for i in (select * from emp where rownum < 5)
Loop
dbms_output.put_line('Current field value is: '||i.Emp_id);
dbms_output.put_line('Current field value is: '||i.emp_name);
end loop;
end;
If I understand you correctly, I think you're after something like:
select name,
desig,
sal,
(select approved from approval_table apv1 where apv1.data = emp.name) name_aprvd,
(select approved from approval_table apv2 where apv2.data = emp.desig) desig_aprvd,
(select approved from approval_table apv3 where apv3.data = emp.sal) sal_aprvd
from empdata emp;
Quite what you expect to do with the information once you've got it, I'm not sure. Maybe you return this as a cursor? Maybe you pass it into a procedure? I'm not sure, but hopefully you have enough information to sort out your requirement?

pl-sql include column names in query

A weird request maybe but. My boss wants me to create an admin version of a page we have that displays data from an oracle query in a table.
The admin page, instead of displaying the data (query returns 1 row), needs to return the table name and column name
Ex: Instead of:
Name Initial
==================
Bob A
I want:
Name Initial
============================
Users.FirstName Users.MiddleInitial
I realize I can do this in code but would rather just modify the query to return the data I want so I can leave the report generation code mostly alone.
I don't want to do it in a stored procedure.
So when I spit out the data in the report using something like:
blah blah = MyDataRow("FirstName")
I can leave that as is but instead of it displaying "BOB" it would display "Users.FirstName"
And I want to do the query using select * if possible instead of listing all the columns
So for each of the columns I am querying in the * , I want to get (instead of the column value) the tablename.ColumnName or tablename|columnName
hope you are following- I am confusing myself...
pseudo:
select tablename + '.' + Columnname as WhateverTheColumnNameIs
from Table1
left join Table2 on whatever...
Join Table_Names on blah blah
Whew- after writing all this I think I will just do it on the code side.
But if you are up for it maybe a fun challenge
Oracle does not provide an authentic way(there is no pseudocolumn) to get the column name of a table as a result of a query against that table. But you might consider these two approaches:
Extract column name from an xmltype, formed by passing cursor expression(your query) in the xmltable() function:
-- your table
with t1(first_name, middle_name) as(
select 1,2 from dual
), -- your query
t2 as(
select * -- col1 as "t1.col1"
--, col2 as "t1.col2"
--, col3 as "t1.col3"
from hr.t1
)
select *
from ( select q.object_value.getrootelement() as col_name
, rownum as rn
from xmltable('//*'
passing xmltype(cursor(select * from t2 where rownum = 1))
) q
where q.object_value.getrootelement() not in ('ROWSET', 'ROW')
)
pivot(
max(col_name) for rn in (1 as "name", 2 as "initial")
)
Result:
name initial
--------------- ---------------
FIRST_NAME MIDDLE_NAME
Note: In order for column names to be prefixed with table name, you need to list them
explicitly in the select list of a query and supply an alias, manually.
PL/SQL approach. Starting from Oracle 11g you could use dbms_sql() package and describe_columns() procedure specifically to get the name of columns in the cursor(your select).
This might be what you are looking for, try selecting from system views USER_TAB_COLS or ALL_TAB_COLS.

insert date from neighbor entry

Table has columns for issue_date, part_num and date_received.
If an issue_date is null, I want to select issue_date of part_num + 1 (the next part number), and insert it in the issue_date column of the part with no issue date.
part_num is sequential.
What sql statement would select then insert the appropriate issue date?
Thank you in advance for any help.
Figured it out with a little self join statement.. thank you delete if you wish!!
Try this:
update t
set t.issue_date = (select issue_date
from t t1
where t1.part_num = t.part_num+1)
where t.issue_date is null
But, if the next part number also doesn't have issue_date, this will ramain null's in issue_date. To solve this problem you can change query to this one (if it's suitable for your application):
update t
set t.issue_date = (select min(issue_date)
from t t1
where t1.part_num > t.part_num)
where t.issue_date is null

Resources