UPDATE VALUES OF COLUMN IN POSTGRESQL - sql

I have 4 tables:
1. matchsal
ID salaray
1 1000
2 2000
3 3000
4 4000
5 5000
2. TABLE1
ID C
1 NA
2 NA
3 NA
4 NA
5 NA
3. TABLE2
ID lfs1 lfs2
1 2 3
2 3 1
3 3 1
4 3 1
5 2 3
4. TABLE3
ID_NIC filternn
1 private
2 public
3 private
4 Private
5 public
what i want is to update table1 with the salary values from matchsal table
with conditions in the others tables, i tried this query:
update TABLE1 LFS
SET C1= (Select SALARY from matchsal ss )
WHERE LFS."ID" IN
( SELECT "ID" from
TABLE2 lfs,
TABLE3 NIC
WHERE lfs."ID"=NIC."ID_NIC"
and lfs.lfs1 <> LFS.lfs2
and filternn in ( 'Private'))
and i got this error:
ERROR: more than one row returned by a subquery used as an expression
SQL state: 21000

The subquery in the SET is causing the problem. It is possible that you want:
SET C1 = (Select ss.SALARY from matchsal ss where ss.id = lfs.id)
But that is just a guess.

Try this:
update TABLE1 LFS
SET C1= (Select ss.SALARY from matchsal ss where lfs.id=ss.id)
WHERE lfs.ID IN
( SELECT ID from
TABLE2 lfs,
TABLE3 NIC
WHERE lfs.ID=NIC.ID_NIC
and lfs.lfs1 <> LFS.lfs2
and filternn in ( 'Private'))

I found the answer ^^"
It is simple thing
update TABLE1 LFS
SET C1= (Select SALARY from matchsal ss where ss.id=LFS."ID" limit 1)
WHERE LFS."ID" IN
( SELECT "ID" from
TABLE2 lfs,
TABLE3 NIC
WHERE lfs."ID"=NIC."ID_NIC"
and lfs.lfs1 <> LFS.lfs2
and filternn in ( 'Private'))
I Just add a limit to the sub query

Related

SQL - Delete specific set of raw in a table using another table

Tabel 1 :
ID1
ID2
ID3
MainID
Location
1
A
X
1AX
VIC
2
B
Y
2BY
SYD
3
C
W
3CW
TAS
4
D
Z
4DZ
TAS
Tabel 2 :
SALESID
QTY
AMT
DIFF
1AX
1
100
2
2BY
2
0
3
3CW
3
5
4DZ
3
12
2
Ignore other fields, I need to delete all raws in Tabel 1 where AMT in Tabel 2 has zero or no value for the SALESID.
For example, after the query, only raws containing 1AX & 4DZ should be remain in Tabel 1.
this can be done by subquery
get all MainID from table2 where amt is 0 or null
delete all rows that equal to previous fetched MainID
delete from table1 where MainID in (
select SALESID from table2 where AMT <=0 or AMT is null
)
You can use exists:
delete from table1
where exists (select 1
from table2 t2
where table1.mainid = t2.salesid and
(t2.amt = 0 or t2.amt is null)
);
Thinking an INNER JOIN would be much faster on larger data sets. Something like this:
DELETE
T1
FROM
Table1 T1
INNER JOIN
Table2 T2 ON T2.SalesID = T1.MainID
WHERE
IsNull(T2.Amt,0) = 0

Update rows in a table based on grouping

I have a table with records of the same type with ID's and a grouping. I need to update the id's of table 1 into table 2 based on the record id from largest to smallest using the position.
Table 1
ID
Group
Name
1
A
Apple
2
A
Apple
3
B
Apple
4
B
Apple
Table 2
ID
recordid
position
group
1
1
250
A
2
2
350
A
3
null
450
A
4
null
550
A
5
3
250
B
6
4
350
B
7
null
450
B
8
null
550
B
update table2
set recordid=T1.ID
From Table1 T1
join Table2 T2 on T2.Group=T1.Group
This isn't distinct so I don't think it's right, but I can't figure it out.
where ?????
the problem is you have multiple Id per group , so you have to choose one :
update table2
set recordid= ( select top 1 T1.ID
From Table1 T1
join Table2 T2 on T2.Group=T1.Group
)
where recordid is null

How to get Oracle to return unique results in a one to many relationship tables with a left join

I have a three tables
Table 1
Id Department
1 A
2 B
3 C
4 D
Table 2
Id DepartId Name
1 1 ABC
2 1 DEF
3 1 ASD
4 2 FGH
5 2 HJK
6 3 ZXC
Table 3
Id Depart Area
1 A pp
2 B
3 C nn
4 D oo
I need the result
Id Depart Name Area
1 A ABC pp
2 B FGH Null
3 C ZXC nn
4 D NULL oo
I need one matching entry from table 2 and table 3 to corresponding entry in the table 1
Do a left join to also get t1 rows without any reference in the t2 table. GROUP BY to get only 1 row per Department.
select t1.id, t1.Department, min(t2.Name)
from t1
left join t2 on t1.id = t2.DepartId
group by t1.id, t1.Department
I think I would do this with a correlated subquery:
select t1.*,
(select t2.name
from t2
where t1.id = t2.DepartId and rownum = 1
) as t2name
from t1;
This saves the overhead of an aggregation. An index on t2(DepartId, name) is optimal for this query.
by the way not the answer to your specific question but if instead of just one you want all the names you can use listagg
SELECT t1.id,
department,
LISTAGG (name, ',') WITHIN GROUP (ORDER BY name) names
FROM t1, t2
WHERE t1.id = t2.departId(+)
GROUP BY t1.id, department
ORDER BY 1
ID Department Names
1 A ABC,ASD,DEF
2 B FGH, HJK
3 C ZXC
4 D

Compare multiple Rows Based on another table

Lets say I have following tables:
Table1
ID Number
1 2
2 34
3 1 <---- Input (ID = 3) ==> (Number = 1)
4 6
5 5
*6* 7 <---- Want to find (Number = 6) because match in Table2
7 22
and Table2
Number Code Att1 Att2 Att3
1 1 1 <-----|
1 2 1 2 <-----|
6 2 f 2 |
6 3 4 3 2 |
2 4 6 |---Match
22 5 2 2 2 |
5 2 h 3 b |
7 1 1 <-----|
7 2 1 2 <-----|
7 h 5 r
So here is my Problem:
I want the IDs from Table1 that have all Code and Attributes from Table2 that a given (variable) input ID has. At the end I want to create a stored procedure/function that gives me all IDs meeting that condition.
As an Example:
Input-ID: 3. Would return ID 6 because Number 7 (mapped from ID 6 in Table1) has the rows Number 1 (mapped from ID 3 in Table1) has. It has more but that doesn't matter, its just important it has all rows the input one has.
(I can't find a solution to comparing a set of rows to another set of rows that is not known before.)
Thanks for any help!
Edit:
To make it more understandible, here what I want in words step-by-step.
Map input ID to Number in Table1
Get All Rows from Table2 having Number from Step 1
Get all Number that have the same (can have more) Rows as from Step 2
Get IDs for that Numbers (and return them)
Try something like this. Haven't tested it, but basically you inner join on all of the attributes that need to match. The HAVING clause is a crude check to make sure that it matched all the rows. Edit: Forgot to add the input ID WHERE clause.
SELECT t1b.ID FROM
Table1 t1a
INNER JOIN Table2 t2a ON t1a.Number = t2a.Number
INNER JOIN Table2 t2b ON t2a.Number <> t2b.Number AND t2a.Code = t2b.CODE AND t2a.Att1 = t2b.Att1 AND t2a.Att2 = t2b.Att2 AND t2a.Att3 = t2b.Att3
INNER JOIN Table1 t1b ON t1b.Number = t2b.Number
WHERE t1a.ID = 3
GROUP BY t1b.ID
HAVING COUNT(*) = (SELECT COUNT(*) FROM Table1 WHERE ID = t1a.ID)
select t11.ID as Id_To_Find,t12.ID as Id_Found
from Table1 t11
join (
select t21.Number as Found,t22.Number as ToFind from Table2 t21
left join Table2 t22 on t21.Code = t22.Code
and t21.Att1 = t22.Att1
and t21.Att2 = t22.Att2
and t21.Att3 = t22.Att3
and t21.Number <> t22.Number
group by t21.Number,t22.Number
having COUNT(*) = (select COUNT(*) from Table2 where Number = t22.Number))
as FindMatches
on t11.Number = FindMatches.ToFind
join Table1 t12 on t12.Number = FindMatches.Found
Kind of hard to understand what you're trying to acheive. As i understood from your example, you want to match the Number for the input ID in Table1 with any column (correct?) in Table2.
With input ID=3, the SELECT will return Number=7. In the IN (...)-condition, you can specify whichever columns in Table2 you want to match to Table1.Number.
DECLARE #Input INT = 3 -- Your input
SELECT DISTINCT t1.Number
FROM Table1 t
INNER JOIN Table2 t2 ON t.Number IN (t2.Number, t2.Code, t2.Att1, t2.Att2, t2.Att3)
INNER JOIN Table1 t1 ON t2.Number = t1.Number AND t.ID <> t1.ID
WHERE t.ID = #Input

SQL Join with multiple row condition in second table

I have a question on SQL join which involve multiple condition in second joined table. Below is the table details
Table 1
pId status keyVal
---- ------- ------
100 1 45
101 1 46
Table 2
pId mode modeVal
100 2 5
100 3 6
101 2 7
101 3 8
I have above two tables and I am trying to join based on below condition to get pId's
pId's which has keyVal = 45 and status = 1 joined with table2 which has mode = 2 and modeVal 5 and mode =3 and modeVal = 6
the result I am expecting is to return pid = 100
Can you please help me with a join query ?
One way is to use GROUP BY with HAVING to count that the number of rows found is 2, of which 2 are matching the condition;
WITH cte AS (SELECT DISTINCT * FROM Table2)
SELECT t1."pId"
FROM Table1 t1 JOIN cte t2 ON t1."pId" = t2."pId"
WHERE t1."status" = 1 AND t1."keyVal" = 45
GROUP BY t1."pId"
HAVING SUM(
CASE WHEN t2."mode"=2 AND t2."modeVal"=5 OR t2."mode"=3 AND t2."modeVal"=6
THEN 1 END) = 2 AND COUNT(*)=2
If the values in t2 are already distinct, you can just remove the cte and select directly from Table2.
An SQLfiddle to test with.
SELECT columns
FROM table1 a, table2 B
WHERE a.pid = B.pid
AND a.keyval = 45
AND a.status = 1
AND (
(B.mode = 2 AND B.modeval = 5)
OR
(B.mode = 3 AND B.modeval = 6)
)
Below query should work for you perfectly
select distinct table1.pid FROM table1 JOIN table2
on table1.pid = table2.pid
WHERE table2.modeValue IN (5,6) AND table2.mode IN (2,3) AND table1.keyVal=45 and table1.status=1;