SQL update by the same table with join another table - sql

I have a Location table in SQL Server:
LocationId | LocationName | Address
========================================
15 AA 111 AAA
17 CC 999 CCC
And I have a Worksite table with WorksiteMark = Null
WorksiteId | WorksiteName | Address | LocationId | WorksiteMark
======================================================================
1 AA 111 AAA 15 Null
2 P 23 P 15 Null
3 F 78 F 15 Null
4 H 16 H 17 Null
5 CC 999 CCC 17 Null
6 W 78 W 17 Null
Finally I need to update WorksiteMark = WorksiteId reference with Location table and I will delete the Location table
WorksiteId | WorksiteName | Address | WorksiteMark
========================================================
1 AA 111 AAA 1
2 P 23 P 1
3 F 78 F 1
4 H 16 H 5
5 CC 999 CCC 5
6 W 78 W 5
Can you help me to create a script for updating WorksiteMark = WorksiteId referencing the Location table?
Thanks

Hope This works for you.
Update W
SET W.WorksiteMark = L1.WorksiteId
FROM #Worksite AS W
INNER JOIN (Select L.LocationId,W2.WorksiteId FROM #Location L INNER JOIN
#Worksite W2 ON L.LocationName = W2.WorkSiteName) AS L1
ON W.LocationId = l1.LocationId

UPDATE [dbo].[Worksite]
SET WorksiteMark = (SELECT WorksiteId FROM [dbo].[Worksite] B WHERE B.WorksiteNAME = [dbo].[Location].LocationName)
from [dbo].[Worksite]
inner join [dbo].[Location] on [dbo].[Location].[LocationId] = [dbo].[Worksite].LocationId

You need a double JOIN with your update, something like;
UPDATE W
SET W.WorksiteMark = W2.WorksiteId
FROM Worksite AS W
INNER JOIN Location AS L
ON L.LocationId = W.LocationId
INNER JOIN Worksite AS W2
ON W2.WorksiteName = L.LocationName

Related

Query to join two tables using two different columns from the first table

I have two tables .
Table A:
Table A ID Table Name owner1ID owner2ID
1 Work1 85 91
2 Work2 86 92
3 Work3 87 93
4 Work4 88 94
5 Work5 89 95
6 Work6 90 96
Table B:
OwnerID 0WNERFIRSTNAME 0WNERlASTNAME
85 A M
86 B N
87 C O
88 D P
90 E Q
91 F R
89 G S
92 H T
86 I U
94 J V
93 K W
95 L X
Can you please help me out in getting a query where i need the table which contains TABLEID OWNERFIRSTNAME and OWNERSECONDNAME.
Expected output:
TableAID 0WNER1FIRSTNAME 0WNER1LASTNAME 0WNER2FIRSTNAME 0WNER2LASTNAME
1 A M F R
You need to join on to TableB twice.
That means you need to give each instance of the table an alias, so you can differentiate which instance you're referring to...
SELECT
TableA.TableAID,
TableB1.0WNERFIRSTNAME AS 0WNER1FIRSTNAME,
TableB1.0WNERlASTNAME AS 0WNER1LASTNAME,
TableB2.0WNERFIRSTNAME AS 0WNER2FIRSTNAME,
TableB2.0WNERlASTNAME AS 0WNER2LASTNAME
FROM
TableA
INNER JOIN
TableB TableB1
ON TableB1.OwnerID = TableA.owner1ID
INNER JOIN
TableB TableB2
ON TableB2.OwnerID = TableA.owner2ID
P.S. Don't Spell 0WNERFIRSTNAME with a ZERO, Spell it OWNERFIRSTNAME!
While MatBaile's answer is the most common practice, your own example shows some problems. First is that we lose info about table 6 for which second owner is not found in second table. This can be easily corrected with left join:
select a.id, a.table_name,
b1.OwnerFirstName O1FN, b1.OwnerLastName O1LN,
b2.OwnerFirstName O2FN, b2.OwnerLastName O2LN
from a
left join b b1 on b1.OwnerId = a.Owner1Id
left join b b2 on b2.OwnerId = a.Owner2Id
What gives us:
ID TABLE_NAME O1FN O1LN O2FN O2LN
---------- ---------- ---- ---- ---- ----
1 Work1 A M F R
2 Work2 I U H T <-- two first owners
2 Work2 B N H T <-- two first owners
4 Work4 D P J V
3 Work3 C O K W
5 Work5 G S L X
6 Work6 E Q <-- null second owner
And second problem - for table 2 we got two entries, because in your example there are two owners with id = 86. I suspect that this is typo, but this can happen in similiar cases. You can leave it as is, or take only last row (if owner changed and you have info about this in some date column), or you can list all owners using listagg(), or take max value. Things are worse when there are more rows connected to 1. and 2. owner, your output is multiplied.
As a curiosity here is unpivot-pivot solution. In this case this query looks more complicated, but if there were 10 columns you had to do 10 joins and in this query only lists of columns requires change.
select *
from (
select id, table_name, type, ownerfirstname, ownerlastname
from (select * from a unpivot (ownerId for type in (owner1ID as 1, owner2ID as 2))) a
join b using (ownerId))
pivot (listagg(ownerfirstname||' '||ownerlastname, ', ') within group (order by null) owner
for type in (1, 2))
SQL Fiddle demo
ID TABLE_NAME 1_OWNER 2_OWNER
---------- ---------- ---------- ----------
1 Work1 A M F R
2 Work2 B N, I U H T <-- listagg() used to aggregate data
3 Work3 C O K W
4 Work4 D P J V
5 Work5 G S L X
6 Work6 E Q

Group by a multiple select request from different tables

so I made this :
select (
SELECT COUNT (*)
from TXN_TOTO
WHERE (CO1 = '1L' OR CO1 = '1') AND OP1 in('P3', 'R1')
) as A,
(
SELECT COUNT (*)
from TXN_TITI
WHERE (CO1 = '1L' OR CO1 = '1') AND OP1 in('P3', 'R1') AND STAT = 6
) as B,
(
SELECT COUNT (*)
from T_TITI tti inner join T_TATA ttdi
ON tti.ID_DINT = ttdi.ID_DINT
WHERE (CO1 = '1L' AND OP1 in('01', '04', 'Z8')) OR (CO1 = '1' AND OP1 in('P3', 'R1')) AND COM = 'O'
) as C
FROM DUAL;
I get result who look like this :
A | B | C
----------
7 | 1 | 9
Both TXN_TOTO and TXN_TITI table have a 'cent' column, I'd like to filter on that in order to get
CENT | A | B | C
----------------
0 | 2 | 0 | 0
1 | 2 | 1 | 4
2 | 3 | 0 | 5
Since I getting my data from 2 different tables I really don't see how to do it.
Thanks.
EDIT : as requested here are example data and result
TXN_TOTO
ID_DINT | CO1 | OP1 | DID_CENT
------------------------------
1 2L Z3 088
2 1L 1 089
3 1 P3 155
4 1L Z3 155
5 1L 1 077
6 1 P3 077
7 1L Z3 077
8 1L 1 077
9 1 P3 022
TXN_TITI
ID_DINT | CO1 | OP1 | DID_CENT |STAT
------------------------------------
1 2L Z3 088 6
2 1L 1 089 6
3 1 P3 155 6
4 1L Z3 155 6
5 1L 1 077 6
6 1 P3 077 6
7 1L Z3 077 6
8 1L Z8 077 6
9 1 R1 022 5
TXN_TATA
ID_DINT | COM |
---------------
1 O
2 O
3 O
4 O
5 N
6 O
7 O
8 O
9 O
Expected results :
DID_CENT | A | B | C
155 1 1 0
077 1 1 1
022 1 0 0
A is only computed from TXN_TOTO
B is only computed from TXN_TITI, only difference is the stat column
C is a join of TITI and TATA, you need to have a O in TATA
select coalesce(A.DID_CENT,B.DID_CENT,C.DID_CENT) DID_CENT,
nvl(sum(A.cnt),0) A, nvl(sum(B.cnt),0) B, nvl(sum(C.cnt),0) C
from
(
SELECT DID_CENT, COUNT (*) cnt
from TXN_TOTO
WHERE (CO1 = '1L' OR CO1 = '1') AND OP1 in('P3', 'R1')
GROUP BY DID_CENT
) A
FULL JOIN
(
SELECT DID_CENT, COUNT (*) cnt
from TXN_TITI
WHERE (CO1 = '1L' OR CO1 = '1') AND OP1 in('P3', 'R1') AND STAT = 6
GROUP BY DID_CENT
) B ON A.DID_CENT=B.DID_CENT
FULL JOIN
(
SELECT DID_CENT, COUNT (*) cnt
from TXN_TITI tti inner join TXN_TATA ttdi
ON tti.ID_DINT = ttdi.ID_DINT
WHERE (CO1 = '1L' AND OP1 in('01', '04', 'Z8')) OR (CO1 = '1' AND OP1 in('P3', 'R1'))
GROUP BY DID_CENT
) C ON B.DID_CENT=C.DID_CENT
GROUP BY coalesce(A.DID_CENT,B.DID_CENT,C.DID_CENT)
this is because CENT data has different values according to your A,B,C.
Dual table cant get more than one row so it is not possible to write such a sql.
Instead,
use
count(*) over(partition by CENT)

Update rows from other rows

how can i update this table (zz col):
id xx yy zz n
---- ----- ----- --- -----
1 AA 20 0 0
2 AA 10 0 1
3 AA 10 0 2
4 BB 45 0 0
5 BB 15 0 1
6 BB 15 0 2
7 BB 15 0 3
[zz = yy where n = 0]
To:
id xx yy zz n
---- ----- ----- --- -----
1 AA 20 20 0
2 AA 10 20 1
3 AA 10 20 2
4 BB 45 45 0
5 BB 15 45 1
6 BB 15 45 2
7 BB 15 45 3
Thanks
update tablename set zz=yy where n=0;
You can join on the same table to do your update.
UPDATE A1
SET A1.zz = A2.yy
from
A AS A1
inner join A AS A2 ON A1.xx = A2.xx AND A2.n = 0
You may need to try this way (not tested, but this should help you)
Your UPDATE statement needs to be a correlated update-- you need some key in A that tells you which row in B to go to in order to retrieve the new value. Your WHERE clause should also be an IN or an EXISTS since it needs to return multiple rows.
UPDATE table1 a
SET a.zz = (SELECT b.yy
FROM table1 b
WHERE b.n = 0
AND a.id = b.id)
WHERE EXISTS (SELECT 1
FROM table1 b
WHERE a.id = b.id);
Assuming the join results in a key-preserved view, you could also
UPDATE (SELECT a.id,
a.yy oldval,
x.yy newval
FROM table1 a,
(SELECT b.id,
b.xx,
b.yy
FROM table1 b
WHERE b.n = 0) x
WHERE a.xx = x.xx)
SET oldval = newval;
Try this query
update tablename
set a.zz=(select a.yy
from tablename a
where a.xx=tablename.xx and a.n=0)
you can try this:
UPDATE table1
SET table1.zz= table2.xx
FROM table2
JOIN table1
ON table1.id=table2.id

Select only complete groups in SQL?

Suppose there are 2 tables as shown below. Table A contains rows in a few groups - 11 (1,2,3) and 22 (4,5,6,7) in this case. Table B contains book rows that indirectly reference groups in table A via B.a_id = A.a_id foreign key relationship):
Table A:
a_id grp
---------
1 11
2 11
3 11
4 22
5 22
6 22
7 22
Table B:
b_id a_id book
--------------
1 1 AA
2 2 AA
3 3 AA
4 1 BB
5 2 BB
6 3 BB
7 1 CC
8 3 CC
9 4 AA
10 5 AA
11 6 AA
12 4 BB
13 5 BB
14 6 BB
15 7 BB
16 6 CC
17 7 CC
I need to select only those book/group combinations that are complete, i.e.
a_id grp book
---------------
1 11 AA
2 11 AA
3 11 AA
1 11 BB
2 11 BB
3 11 BB
4 22 BB
5 22 BB
6 22 BB
7 22 BB
11 CC, 22 AA or 22 CC are not eligible, as they do not represent complete groups.
One way to get the desired result is to use row counts by each group in a subquery, but its seems kind of shaky. Any other ideas?
Thanks!
Edit: I don't think that the referenced question is really the same problem.
This is what I could come up with:
select
A.a_id, A.grp, B.book
from
A
inner join B
on A.a_id = B.a_id
left outer join
(select distinct A.grp, B.book
from A, B
where not exists
(
select *
from A a2
inner join B b2
on a2.a_id = b2.a_id
where
a2.a_id = A.a_id
and a2.grp = A.grp
and b2.book = B.book
)
) T1 -- < -- represents incomplete book/group combos
on A.grp = T1.grp
and B.book = T1.book
where
T1.grp is null -- < -- exclude incomplete book/group combos

joining two or more tables in sql

I have three tables like I describe below:
TransactionHeader
ID | ProcessID | BillingHeaderID
1 1 1
2 2 2
TransactionDetail
ID | ProcessID | BillingDetailID
1 1 1
2 1 2
BillingDetail
BillingDetailID | BillingHeaderID | Amount
3 2 10000
4 2 20000
5 2 10000
6 1 10000
7 1 10000
I'm doing this so far
select
b.ID as ID_TransacHeader,
a.ID as ID_TransacDetail,
b.ProcessID
,a.BillingDetailID as Before
,c.BillingDetailID as After
from TransactionDetail a
inner join TransactionHeader b on a.ProcessID = b.ProcessID
inner join billingdetail c on b.BillingHeaderID = c.BillingHeaderID
what I'd like to get as a result something like this:
ID_TrnsacHeader | ID_TransacDetail | ProcessID | Before | After
1 1 1 1 6
1 2 1 2 7
The problem is my query above resulting something like this :
ID_TrnsacHeader | ID_TransacDetail | ProcessID | Before | After
1 1 1 1 6
1 2 1 2 6
1 1 1 1 7
1 2 1 2 7
My goal is to show difference between BillingDetailID on table TransactionDetail which is i called by "Before" and BillingDetailID on table BillingDetail which is i called by "After".
Anyone can give me a directions?
Thanks in advance
try this.......
select
b.ID as ID_TransacHeader,
a.ID as ID_TransacDetail,
b.ProcessID
,a.BillingDetailID as Before
,c.BillingDetailID as After
from TransactionDetail a
inner join TransactionHeader b on a.ProcessID = b.ProcessID
inner join billingdetail c on b.BillingHeaderID = c.BillingHeaderID and a.billingdetailid = c.billingdetailid
To join two or more tables this example might help you:
select *
from
tableA a
inner join
tableB b
on a.common = b.common
inner join
TableC c
on b.common = c.common