Update multiple rows with different values in Oracle - sql

I am trying to update multiple rows using an inner view in oracle.
The select statement for updating this view is:
select count(distinct a.numCount) as numCount, a.accNum as accNum ,
s.unitNum as unitNum
from tableA a,tableS s where a.accNum is not null and s.fk_id=
(select id from tableD where sid=a.accNum )
group by a.accNum ,s.unitNum ;
Update statement that I am trying is below:
update
(select count(distinct a.numCount) as numCount, a.accNum as accNum ,
s.unitNum as unitNum
from tableA a,tableS s where a.accNum is not null and s.fk_id=
(select id from tableD where sid=a.accNum )
group by a.accNum ,s.unitNum ) k
set k.unitNum=k.numCount;
I am trying to update unitNum with value of numCount.
The above query is not working when used as a view.
Is there another way to update this in Oracle.
Please suggest.
Structure of the tables are as below:
TableA
accNum numCount
-----------------------
111 1
222 5
333 2
111 1
111 1
222 5
222 2
TableS
fk_id unitNum
-----------------------
123 0
768 0
734 0
TableD
ID sid
-----------------------
123 222
768 111
734 333
Output should be as below:
TableS
fk_id unitNum
-----------------------
123 3
768 3
734 1
Please suggest

update tableS s
set unitNum=
(select count(distinct a.numCount) as numCount
from tableA a, tableD d
where s.fk_id=d.id and d.sid=a.accNum
);

Related

sql : join table ,return record with count 1

I have a table mt table
It stores transactions.
Each transaction has a billing and its joined by external_id field
I want to return data from mt table where the billing table has only one joined record.
So in this case i would return (mttable, id:4 and 2. It's external_id 111 and 222 has only one record in billing table)
mt table
id external_id
--- -----------
1 444
2 222
3 333
4 111
billing table
id external_id
--- -----------
3 444
4 444
5 333
6 333
7 222
8 111
You could just use a basic GROUP BY query here:
SELECT mt.id, mt.external_id
FROM mt
INNER JOIN billing b ON b.external_id = mt.external_id
GROUP BY mt.id, mt.external_id
HAVING COUNT(*) = 1;
Demo
Hmmm . . .
select mt.*
from mt
where (select count(*)
from billing b
where mt.external_id = b.external_id
) = 1;
You can do something like the following:
SELECT * FROM mt WHERE external_id IN
(SELECT external_id FROM billing GROUP BY external_id HAVING COUNT(*) = 1)
There are few other options also, Like NOT EXISTS:
select t.*
from mt t join billing b on t.external_id = b.external_id
where not exists
(select 1 from billing bb
where mt.external_id = b.external_id and b.id <> bb.id);
Or You can also use the analytical function count as follows:
select * from
(select t.*, count(1) over (partition by b.external_id) as cnt
from mt t join billing b on t.external_id = b.external_id)
where cnt = 1

Sql - Getting Sum on the join table

I just want to get the result which displays the reference which is not tallied in sum of table2. when i run my query below it will give me an wrong sum which it gets doubled even if group by cusid ,refno.
Table 1
RefNo
CusID
TotalAmount
1
1001
50
2
1001
30
3
1002
40
Table 2
RefNo
CusID
Particular
Amount
1
1001
Paper
30
1
1001
Pencil
30
2
1001
Ball
15
2
1001
Rubber
20
3
1002
Laptop
50
select * from Table1 a
INNER JOIN (Select CusID,RefNo, SUM(Amount) as CorrectTotal from Table2 group by
CusID,RefNo,
)b
ON b.CusID= a.CusID AND b.RefNo= a.RefNo
where a.TotalAmount != CorrectTotal
Expected Result
If you do it with FULL JOIN and with GROUP BY, you will also get rows where there is no record in the other table.
SELECT COALESCE(a.RefNo, b.RefNo) AS RefNo
, COALESCE(a.CusID, b.CusID) AS CusID
, a.TotalAmount
, SUM(b.Amount) AS CorrectTotal
FROM table1 a
FULL JOIN table2 b ON a.RefNo = b.RefNo
AND a.CusID = b.CusID
GROUP BY COALESCE(a.RefNo, b.RefNo)
, COALESCE(a.CusID, b.CusID)
, a.TotalAmount
ORDER BY 1, 2
Output
RefNo
CusID
TotalAmount
CorrectTotal
1
1001
50
60
2
1001
30
35
3
1002
40
50
8
888
88
(null)
9
999
(null)
99
See running demo on SQL Fiddle.
The other answer will work, but if you don't want to mess with a GROUP BY on the whole query you can also use an APPLY to do this:
SELECT a.*, c.CorrectAmount
FROM Table1 a
OUTER APPLY (
SELECT SUM(Amount) AS CorrectAmount
FROM Table2 b
WHERE b.CusID = a.CusID AND b.RefNo = a.RefNo
) c
WHERE a.TotalAmount <> c.CorrectAmount

Oralce SQL nested or inner join when you need to compare the same table but different rows with unique ID values

I'm having a trouble writing a query in ORACLE. I have a Table that contains values. for example:
ID quantity partID
123 50 10
100 20 10
100 30 11
123 null 8
456 null 100
789 25 123
456 50 9
I want to get all rows that has same ID but quantities to be 50 and null (exact same pairs of 50 and null only). for the given example I would like to get:
ID quantity partID
123 50 10
123 null 8
456 50 9
456 null 100
I tried inner join but it doesn't provide the exact output as expected.
You may try :
select ID, quantity, partID
from tab
where ID in
(
select ID
from tab
where nvl(quantity,50)=50
group by ID
having count(distinct nvl(quantity,0) )>1
);
ID QUANTITY PARTID
123 50 10
123 (null) 8
456 (null) 100
456 50 9
SQL Fiddle Demo
P.S. you may get the same results by commenting out having count(ID)=2 also but for those cases there may not exist one of 50 or null for values of quantity.
You can use exists:
select t.*
from t
where (t.quantity = 50 and
exists (select 1 from t t2 where t2.id = t.id and t2.partid = t.partid and t2.value is null)
) or
(t.quantity is null and
exists (select 1 from t t2 where t2.id = t.id and t2.partid = t.partid and t2.value = 50)
) ;

SQL Server: How do I check whether records exist for each group in a list of groups?

I have a TableA:
TeamID PersonID
... ...
1 100
2 101
2 105
2 444
3 501
... ...
Also TableB
PersonID CourseID
... ...
444 c103
444 c2048
101 c3214
... ...
How do I write a simple query such that, for example, I can find whether each person in Team 2 has at least one CourseID associated in TableB. The result for my example is:
TeamID PersonID HasCourse
2 101 1
2 105 0
2 444 1
The shorter the query the better, ideally not using loops.
I would just use case exists:
select a.*,
(case when exists (select 1 from b where b.personid = a.personid)
then 1 else 0
end) as hascourse
from a
where team_id = 2;
Just another method.
select a.TeamID, a.PersonID,
iif(count(b.CourseID)>0,1,0) as HasCourse
from TableA a
left join TableB b on b.PersonID = a.PersonID
where a.TeamID = 2
group by a.TeamID, a.PersonID;

SQL. How to select multiple rows by using the MIN and GROUP BY

ID UserId Name Amount RewardId
----------------------------
1 1 James 10.00 1
2 1 James 10.00 2
3 1 James 10.00 3
4 2 Dave 20.00 1
5 2 Dave 20.00 3
6 3 Lim 15.00 2
I'm trying to insert to another table, and this is the result that i'm struggling with:
Tbl1ID RewardId
------------------
1 1
1 2
1 3
4 1
4 3
6 2
I'm trying to get the MIN(ID) of each person and select all the RewardId that belong to that person.
You could do a simple self join to get the minimum id value per userid/rewardid combination;
SELECT MIN(a.id) Tbl1ID, b.RewardId
FROM mytable a
JOIN mytable b
ON a.name = b.name
GROUP BY b.userid, b.rewardid
ORDER BY tbl1id, rewardid;
An SQLfiddle to test with.
If you are running SQL Server 2008+, you can simplify it by using Window Function.
INSERT INTO AnotherTable (Tbl1ID, RewardID)
SELECT MIN(ID) OVER (PARTITION BY Name),
RewardID
FROM SourceTable
SQLFiddle Demo
Try this
SELECT tbl1id,RewardID From
table1 S JOIN
(
SELECT MIN(ID) as tbl1id,Name FROM table1 GROUP BY Name
) T ON T.Name = S.Name
ORDER BY tbl1id
FIDDLE DEMO
Output:
Tbl1ID RewardId
----------------
1 1
1 2
1 3
4 1
4 3
6 2
If you want insert into new table then try this out
Insert into Newtable (tbl1id,RewardID)
SELECT tbl1id,RewardID from
table1 S JOIN
(
SELECT MIN(ID) as tbl1id,Name
FROM table1
GROUP BY Name
) T ON T.Name = S.Name
ORDER BY tbl1id;
FIDDLE DEMO