identify NULL and update for same key column in oracle - sql

I have a test table having below details:
ID Key_COLUMN final_Value
1 aaa 1234
2 bbb 2345
3 bbb NULL
4 ccc 456
5 ccc 145
Desired Output:
--final_value updated from NULL to 2345 based key_column (bbb)
ID Key_COLUMN final_Value
1 aaa 1234
2 bbb 2345
3 bbb 2345
4 ccc 456
5 ccc 145
Identify KEY column having NULL and value and update NULL with the value.
this update requied on huge amount of data
Please assist.

You can use window functions:
select t.*,
coalesce(final_value, max(final_value) over (partition by key_column)) as imputed_final_value
from t;
If you wanted an update -- to actually change the data -- you can use a correlated subquery:
update t
set final_value = (select t2.final_value
from t t2
where t2.key_column = t.key_column and
t2.final_value is not null and
rownum = 1
)
where final_value is null;

Related

Outer join and unique records in each table

TableA
------
IntId EvId Name Phone1
===== ==== ==== ======
100 aaa xxx 11111
101 bbb yyy 22222
102 ccc zzz 33333
103 bbb asd 44444
104 bbb sdf 55555
TableB
------
IntId ASId Grp Phone2
===== ==== ==== ======
201 bbb yyy 6666
202 ccc zzz 7777
203 bbb asd 8888
204 bbb kkf 9999
205 ddd esd 0000
206 eee ffr 1001
I want to join TableA with TableB using TableA.EvId = TableB.ASId to output {IndId, EvId, Name, Phone1, Grp, Phone2} (using outerjoin as I want all records in TableA with matching TableB columns)
I could do it using below query, but it is giving me duplicates since EvId and ASId have duplicates.
SELECT a.IntId, a.EvId, a.Name, a.Phone1, b.Grp, b.Phone2
FROM TableA a
LEFT OUTER JOIN TableB b
ON a.EvId = b.ASId
If EvId are duplicates, consider that record which has max IntId. Same rule for TableB
My final output should be like this - all unique EvId's in TableA using outerjoin on B
IntId EvId Name Phone1 Phone2 Grp
100 aaa xxx 11111 null null
104 bbb sdf 55555 9999 kkf
102 ccc zzz 33333 7777 zzz
Can you please help me with the query?
You can use ROW_NUMBER():
SELECT a.IntId, a.EvId, a.Name, a.Phone1, b.Grp, b.Phone2
FROM TableA a LEFT OUTER JOIN
(SELECT b.*,
ROW_NUMBER() OVER (PARTITION BY ASId ORDER BY IntID DESC) as seqnum
FROM TableB b
) b
ON a.EvId = b.ASId AND b.seqnum = 1;

SQL query update conditional

I have 2 tables
aaa
on_date datetime null,
channel_id numeric(10,0) null,
type_id numeric(10,0) null,
amount numeric(10,0) null
bbb
channel_id numeric(10,0) null
type_id numeric(10,0) null
I want to do an update to aaa.amount to 0 of
only the common channel_ids and type_ids when bbb.type_id is not
null
or
of only the common channel_ids and ALL the type_ids when the
bbb.type_id is null
aaa
2014-09-13 1 3 12
2014-09-13 1 4 16
2014-09-13 2 1 11
bbb (case 1. )
1 3
bbb (case 2. )
1 null
In first case only the first aaa record should have amount = 0
In the second case the first 2 records of aaa should have amount = 0
Thank you
Try this:
update a
set a.amount=0
from aaa a inner join bbb b
on a.channel_id=b.channel_id
where ((a.channel_id=b.channel_id and a.type_id=b.type_id and b.type_id IS NOT NULL)
OR (a.channel_id=b.channel_id and b.type_id IS NULL))
you need to somthing like following as per i understand your question
UPDATE
aa
SET
aa.amount = 0
FROM
aaa aa
JOIN
bbb bb ON aa.channel_id =bb.channel_id
WHERE
(aa.type_id = bb.type_id AND bb.type_id is not null )
OR
(bb.type_id is null)
Hope it will help to you.

Select records from a table where two columns are not present in another table

I have Table1:
Id Program Price Age
12345 ABC 10 1
12345 CDE 23 3
12345 FGH 43 2
12346 ABC 5 4
12346 CDE 2 5
12367 CDE 10 6
and a Table2:
ID Program BestBefore
12345 ABC 2
12345 FGH 3
12346 ABC 1
I want to get the following Table,
Id Program Price Age
12345 CDE 10 1
12346 CDE 2 5
12367 CDE 10 6
I.e get the rows from the first table where the ID+Program is not in second table. I am using MS SQL Server express 2012 and I don't want to add any columns to the original databases. Is it possible to do without creating temporary variables?
Several ways to do this, here's one using not exists:
select *
from table1 t1
where not exists (
select 1
from table2 t2
where t1.id = t2.id and t1.program = t2.program
)
One possible variant is to use LEFT JOIN:
SELECT
Table1.*
FROM
Table1
LEFT JOIN Table2
ON Table1.ID = Table2.ID
AND Table1.Program = Table2.Program
WHERE
Table2.ID IS NULL

Oracle 11g - Creating a side by side comparison of table comlumn data

I have a query where I need to extract data in a regular table and put two rows of data into a single row.
I have rows that consist of
StudentID AUDIT_ACTN Audit_Date .....
aaa A 01/01/2010
aaa A 03/04/2011
aaa A 02/02/2013
aaa D 09/10/2010
aaa D 05/06/2011
aaa D 06/07/2013
aaa A 11/12/2014~
bbb A 01/01/2010
bbb A 03/04/2011
bbb A 02/02/2013
bbb D 09/10/2010
bbb D 05/06/2011
bbb D 06/07/2013
bbb A 11/12/2014~
I want output like this
StudentID AUDIT_ACTN Audit_Date StudentID AUDIT_ACTN Audit_Date
aaa A 01/01/2010 aaa D 09/10/2010
aaa A 03/04/2011 aaa D 05/06/2011
aaa A 02/02/2013 aaa D 06/07/2013
aaa A 11/12/2014 NULL NULL NULL
bbb A 01/01/2010 bbb D 09/10/2010
bbb A 03/04/2011 bbb D 05/06/2011
bbb A 02/02/2013 bbb D 06/07/2013
bbb A 11/12/2014 NULL NULL NULL
The A & D data rows are related, a= add the something to the record and d = delete something from the record (something is an indicator). These is logical in that you must add something before you delete it and you cannot add it twice, without deleting it first.
My current script is probably going down the wrong track but here goes;
select a.StudentId,a.Audit_Date,a.AUDIT_ACTN,d.StudentId,Audit_Date,d.AUDIT_ACTN,
from table a
join
(select *
from
(Select StudentId, Audit_Date,AUDIT_ACTN
from table b
Where b.AUDIT_ACTN='D'
order by Audit_Date
)
where rownum=1
) d on a.StudentId = d.StudentId
and a.AUDIT_ACTN='A'
and Select * from (Select Audit_Date
Order by a.StudentId, a.Audit_Date
I know this is wrong but where do I go from here. If anyone can help and point me in the right direction. It would be appreciated.
My current attempts bring me zero rows, when I take out the rownum it brings me a x join returning 12 rows in this case.
thanks
Roger
I think you need aggregate function like below
select
A.StudentId,A.Audit_Date,A.AUDIT_ACTN,
D.StudentId,D.Audit_Date,D.AUDIT_ACTN
from
(Select StudentId, Audit_Date,AUDIT_ACTN,ROW_NUMBER()
OVER (PARTITION BY StudentId order by audit_date) rn
from table b
Where b.AUDIT_ACTN='D'
) D
FULL OUTER JOIN
(Select StudentId, Audit_Date,AUDIT_ACTN,ROW_NUMBER()
OVER (PARTITION BY StudentId order by audit_date) rn
from table b
Where b.AUDIT_ACTN='A'
) A
on A.rn = D.rn and A.StudentId = B.StudentId
I hope this will work

Problem with joining db tables

I have problem when joining tables (left join)
table1:
id1 amt1
1 100
2 200
3 300
table2:
id2 amt2
1 150
2 250
2 350
my Query:
select id1,amt1,id2,amt2 from table1
left join table2 on table2.id1=table1.id2
My supposed o/p is:
id1 amt1 id2 amt2
row1: 1 100 1 150
row2: 2 200 2 250
row3: 2 200 2 350
I want o/p in row3 as
2 null 2 350
ie I want avoid repetition of data(amt1).
This really is a formatting issue which is best handled by the client. For instance, in SQL*Plus we can use BREAK ....
SQL> select t1.*, t2.* from t1, t2
2 /
A B C D C1
--- --- --- --- ----------
aaa bbb ccc ddd 111
aaa bbb ccc ddd 222
SQL> break on a on b on c on d
SQL> select t1.*, t2.* from t1, t2
2 /
A B C D C1
--- --- --- --- ----------
aaa bbb ccc ddd 111
222
SQL>
Note: in the absence of any further information I opted for a Cartesian product.
edit
BREAK is a SQLPlus command, which suppresses duplicate columns in our rows. It only works in the SQLPlus client. As might be expected, it is covered in Oracle's SQL*Plus User Guide. Find out more.
I used BREAK as an example of the proper way of doing things, because it is clean and correctly implements the separation of concerns. It you are using a different client you would need to use its formatting capabilities. It is possible to tweak the SQL (see below) but that diminishes the utility of the query, because we cannot reuse the query in other places which don't want to suppress the duplicated values.
Anyway, here is one solution which uses the ROW_NUMBER() analytic function in an inline view.
SQL> select * from t1
2 /
A B C D ID
--- --- --- --- ----------
eee fff ggg hhh 1
aaa bbb ccc ddd 2
SQL> select * from t2
2 /
C1 ID
---------- ----------
333 2
111 1
222 2
444 2
SQL> select t1_id
2 , case when rn = 1 then a else null end as a
3 , t2_id
4 , c1
5 from (
6 select t1.id as t1_id
7 , row_number () over (partition by t1.id order by t2.c1) as rn
8 , t1.a
9 , t2.c1
10 , t2.id as t2_id
11 from t1, t2
12 where t1.id = t2.id
13 )
14 order by t1_id, rn
15 /
T1_ID A T2_ID C1
---------- --- ---------- ----------
1 eee 1 111
2 aaa 2 222
2 2 333
2 2 444
SQL>
I chose not to use LAG(), because that only works with fixed offsets, and it seemed likely that the number of rows in T2 would be variable.
Assuning you want all data in a single row, you just do a union select...
Select fieldA from tableA
Union
Select fieldB from TableB
Note that you need to cast the datatype to be the same for both tables.
If you need an other answer, please format the expected result better ;)
Ok...
You have corrected the formating...
In the case above I would simply return 2 cursors from my query. The example data provides no field to link both tables together, so i see no way to join them in a resonable manner. It is possible for a sproc to return several resultsets.
You've done the cartesian product of the two tables since you haven't specified any join criteria. In order to eliminate duplicates, you need to specify how you want the tables to join.
For example, you could try
select * from table1, table2 where table2.val = 111;
Your example doesn't have any join key, so there's no obvious value to join the tables on. But is a more typical example, there would be a related value in both tables so that you could join them together in a meaningful way.
You seem to be doing a cross join here. I suspect you wanted either an equi join or a left outer join.