Update rows from other rows - sql

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

Related

Joining on optional

I have 2 tables:
Table1 - Criteria
Office_ID Bus_Stream Bus_Criteria Crit_Value
1 ABC 0 20
1 ABC 1 21
1 ABC 2 7
2 ABC 0 15
2 ABC 1 12
2 ABC 2 21
3 XYZ 1 17
3 XYZ 2 3
Table2 - Limit
Bus_Stream GroupID TypeID SubgroupID Bus_Limit
ABC 20 21 7 50
ABC 15 12 21 100
XYZ 99 17 3 120
I need to create a join that allows me to pull back:
Result
Bus_Stream Office_ID GroupID TypeID SubgroupID Bus_Limit
ABC 1 20 21 7 50
ABC 2 15 12 21 100
XYZ 3 (null) 17 3 120
Essentially, I need to join Table1.Crit_Value based on the following:
Table1.Bus_Criteria Table2
0 GroupID
1 TypeID
2 SubGroupID
with the added complication that if one or two of the 0/1/2 values from Bus_Criteria is missing, the joins will still occur on the remaining criteria.
I have tried a number of combinations of AND/OR on the join to no avail.
Any ideas folks?
This may be what you're after.. use a case statement on the join.
The problem here is your data in t2 isn't normalized, you could also unpivot the 3 data columns in t2 so the join is more natural.
SELECT T2.Bus_Stream, T1.Office_ID, T2.GroupID, T2.TypeID, T2.SubGroupId, T2.bus_Limit
FROM T1
INNER JOIN T2
on T1.Bus_Stream = T2.Bus_Stream
and T1.Crit_value = case when T1.Bus_Critiera = 0 then T2.GroupID
when T1.Bus_Critiera = 1 then T2.TypeID
when T1.Bus_Critiera = 2 then T2.SubGroupID
end
Did you try something like this?
SELECT
t1.*, t2.*
FROM Table1 t1
INNER JOIN Table2 t2 ON
t1.Bus_Stream = t2.Bus_Stream AND
CASE
WHEN t1.Bus_Criteria = 0
THEN t2.GroupID = t1.Crit_Value
WHEN t1.Bus_Criteria = 1
THEN t2.TypeID = t1.Crit_Value
ELSE
t2.SubGroupID = t1.Crit_Value
END

Hiding a row where value = 0 but count its other column values in total calculations - sql2008

I have tables like that: (C1-C2 varchar(10), C3-Number int)
WaitingData
C1 C2 C3 Number
A B 1 10
A B 2 0
A B 3 4
X B 4 2
CompletedData
C1 C2 C3 Number
A B 1 5
A B 2 2
A B 3 0
X B 4 12
I am using the query below to represent the data:
Select wd.C1,wd.C2,wd.C3,wd.Number as NW,cdd.Number as NC
into #AllData
from (Select C1,C2,C3,sum(Number) from WaitingData group by C1,C2,C3) wd
outer apply (Select C1,C2,C3,sum(Number)
from CompletedData cd
where wd.C1=cd.C1 and wd.C2=cd.C2 and wd.C3=cd.C3
) cdd
Select * from #AllData
union
Select C1='Total',C2='Total',C3=-1, sum(NW),sum(NW)
from #AllData
This is giving me an output like:
C1 C2 C3 NW NC
A B 1 10 5
A B 2 0 2
A B 3 4 0
X B 4 2 12
Total Total -1 16 19
However, I want to hide the rows that has no NW but calculate its regarding values while calculating the Total row (see NC below). The output I want is like:
C1 C2 C3 NW NC
A B 1 10 5
A B 3 4 0
X B 4 2 12
Total Total -1 16 19
I could not find a way to provide an output like this. Any help would be so appreciated!
------------------------------EDIT---------------------------------------
------------------------------EDIT---------------------------------------
When I have data in the tables like below, the outer apply is not working like I want, it does not include the data A B 2.
WaitingData
C1 C2 C3 Number
A B 1 10
A B 3 4
X B 4 2
CompletedData
C1 C2 C3 Number
A B 1 5
A B 2 2
X B 4 12
And the output would be like:
C1 C2 C3 NW NC
A B 1 10 5
A B 3 4 NULL
X B 4 2 12
Total Total -1 16 17
In this situation, what can I do to count "2" NC value having by A B 2 on the final result and see NC as 19 instead 17, except inserting all the records that included by CompletedData but WaitingData? (need an efficient way)
Wrap the final result with one more select and exclude rows where NW = 0.
select * from
(
Select * from #AllData
union
Select C1='Total',C2='Total',C3=-1, sum(NW),sum(NC)
from #AllData
) t
where NW <> 0
Edit: Using a full join to get all values from both tables.
with t as
(select coalesce(w.c1,c.c1) as c1,coalesce(w.c2,c.c2) as c2,coalesce(w.c3,c.c3) as c3
, coalesce(w.number,0) as nw , coalesce(c.number,0) as nc
from waitingdata w
full join completeddata c on w.c1 = c.c1 and w.c2=c.c2 and w.c3=c.c3)
select * from
(select * from t
union all
Select C1='Total',C2='Total',C3=-1, sum(NW),sum(NC)
from t) x where nw <> 0
You can do all of this in one query, without temporary tables, intermediate results, subqueries, or UNION by using the ROLLUP operator:
SELECT
WD.C1,
WD.C2,
WD.C3,
SUM(WD.Number) AS NW,
SUM(CD.Number) AS NC
FROM
dbo.WaitingData WD
LEFT OUTER JOIN CompletedData CD ON
CD.C1 = WD.C1 AND
CD.C2 = WD.C2 AND
CD.C3 = WD.C3
GROUP BY
WD.C1,
WD.C2,
WD.C3
WITH ROLLUP
HAVING
GROUPING_ID(WD.C1, WD.C2, WD.C3) IN (0, 7) AND
SUM(WD.Number) <> 0

SQL update by the same table with join another table

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

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

Update statement with duplicates values

I have a table like this
Clubcard
AssoicaticeCard MainCard custID
A A 1
B B 1
C A 1
AA AA 2
BC BC 2
CC CC 2
Ar Ar 3
Bs Bs 3
Cv Cv 3
Now I need the result to be set like this where my AssoicaticeCard and MainCard have are be linked up properly.
I need the result like this to be shown. How to write an update statement for this to get achieved?
AssoicaticeCard MainCard custID
A A 1
B A 1
C A 1
AA AA 2
BC AA 2
CC AA 2
Ar Ar 3
Bs Ar 3
Cv Ar 3
I have an table with data like with which is inconsistency, now need to write an update statement to solve the issue. My table have around 1 million records.
update T1
set MainCard = T2.AssoicaticeCard
from YourTable as T1
inner join
(
select min(AssoicaticeCard) as AssoicaticeCard,
custID
from YourTable
group by custID
) T2
on T1.custID = T2.CustID
update clubcard set Maincard = 'A' where custID = 1;
update clubcard set Maincard = 'AA' where custID = 2;
update clubcard set Maincard = 'Ar' where custID = 3;