Update in child table, only one value got updated - sql

Below I am trying to update value of a parent table from child table and counting matching values. Tables in my db:
issue_dimension with id = issue_id and have column accno.
star_schema with id star_id,this Child column have fk issue_id and column book_frequency
The book_frequency need to match the count of each accno in parent table , I tried this
update [test1] .[dbo] .star_schema
set [book_frequency] = (
select top 1 COUNT([issue_dimension].ACCNO)as book_frequency
from issue_dimension
group by ACCNO having (COUNT(*)>1) and
issue_dimension.ACCNO = star_schema .ACCNO
)
It only updates only 1st value count issue_dimension. I need to count every accno in issue_dimension and update it to matching accno of star_schema.
I never did update by joining two or more tables , can anyone help in this with joins

UPDATE s
SET [book_frequency] = i.CNT
FROM [test1].[dbo].star_schema s
INNER JOIN
(
SELECT ACCNO, COUNT(*) as CNT
FROM issue_dimension
GROUP BY ACC_NO
HAVING COUNT(*)>1
) i on (s.ACCNO = i.ACCNO)
I didn't check it but it should works

Try in this way, without grouping, just with the WHERE clause:
UPDATE [test1].[dbo].star_schema SET
[book_frequency] =
(
SELECT COUNT([issue_dimension].ACCNO)
FROM issue_dimension
WHERE issue_dimension .ACCNO = star_schema.ACCNO
HAVING COUNT(*)>1
)

It's not fully clear to me so the answer is a bit of guessing:
update s set
book_frequency = t.qty
from star_schema s
join issue_dimension i on s.issue_id = s.issue_id
join (select count(*) as qty, accno
from issue_dimension
group by accno
) t on i.accno = t.accno

Here's the example from BOL that does the kind of thing you're looking for, using AW:
USE AdventureWorks2008R2;
GO
UPDATE Sales.SalesPerson
SET SalesYTD = SalesYTD +
(SELECT SUM(so.SubTotal)
FROM Sales.SalesOrderHeader AS so
WHERE so.OrderDate = (SELECT MAX(OrderDate)
FROM Sales.SalesOrderHeader AS so2
WHERE so2.SalesPersonID = so.SalesPersonID)
AND Sales.SalesPerson.BusinessEntityID = so.SalesPersonID
GROUP BY so.SalesPersonID);

Related

How to set a value in 1 table according to the count of a value in another table

The database I am using (It is in a relationship with table 1):
Sample Data for Table1
I want to set Present Count in Accounts according to the number of 'P' characters in Table1.Attendance (Right now, it is manually set). I tried making a 'Counting' query that looks like this
UPDATE Accounts SET [Present Count] = (SELECT Count(*) FROM Table1 WHERE Table1.Attendance = 'P')
WHERE Accounts.Username = Table1.Username
I tried this too
SELECT Count(Table1.Attendance) AS PCount HAVING ((Count(Table1.Attendance))='P'), Count(Table1.Attendance) AS ACount HAVING (Count(Table1.Attendance))='A'
FROM Table1
GROUP BY Username
But this won't work, giving no error, no update or anything
This as well:
UPDATE Accounts
SET [Present Count] = (SELECT Count(*)
FROM Table1
WHERE Table1.Attendance = 'P' AND
Accounts.Username = Table1.Username
);
This displays the count i have set in the table manually, not the count calculated from the total number of 'P's
You could try using a inner join on the subquery for count group by username
UPDATE A
SET A.[Present Count] = t.my_count
FROM Accounts AS A
INNER JOIN (
SELECT username, Count(*) AS my_count
FROM Table1
WHERE Table1.Attendance = 'P'
GROUP BY username
) AS t ON A.Username = t.Username
The correct syntax is:
UPDATE Accounts
SET [Present Count] = (SELECT Count(*)
FROM Table1
WHERE Table1.Attendance = 'P' AND
Accounts.Username = Table1.Username
);
EDIT:
What values does this return?
SELECT UserName, Count(*)
FROM Table1
WHERE Table1.Attendance = 'P'
GROUP BY Username
Perhaps what you see as 'P' isn't really 'P' and you are just getting 0 for everything because nothing matches.

Multi part identifier could not be found using a temp table

I have the following query which populates a temporary table:
with CTE as
(
select a.accountid as 'myid',
a.new_mprnnumber,
a.new_customernumber,
b.*,
row_number()
over (partition by new_customernumber -- add additional partitions as you would group bys
order by billingPeriodEndDate desc) as r_ord
from [CRM].[crm4_MSCRM].[dbo].[AccountExtensionBase] a
inner join bill b
on a.new_mprnnumber = b.MPRN
where new_accountstage = 7
and new_accounttype = 2
)
select *
into #tempCTE
from CTE
where r_ord = 1
After gathering the information in the temporary table I want to iterate through each record and update the main table using the accountid but using the following statement:
update [CRM].[crm4_MSCRM].[dbo].[AccountExtensionBase]
set new_invoicenumber = invoicenumber
where accountid = #tempCTE.myid
I am getting the error that the multi part identifier could not be bound, any idea on what is causing this issue?
You need to bring in the temporary table:
update aeb
set new_invoicenumber = t.invoicenumber
from [CRM].[crm4_MSCRM].[dbo].[AccountExtensionBase] aeb join
#tempCTE t
on aeb.accountid = t.myid;
As a note, you don't need a temporary table. You can just do:
with tempCTE as ( . . . )
update aeb
set new_invoicenumber = t.invoicenumber
from [CRM].[crm4_MSCRM].[dbo].[AccountExtensionBase] aeb join
tempCTE t
on aeb.accountid = t.myid
where tempCTE.r_ord = 1

Update only first record from duplicate entries in SQL Server

I need help trying to update a table that has multiple duplicate records, but I am stuck.
I have this table, and I need to update im_cust9 with the alt_item_id1 value.
The query I am using to get this result from the table is the following:
SELECT
o.item_id, o.alt_item_id1, o.im_cust9, o.owner_id, o.if_updatestamp
FROM
item_master o
INNER JOIN
(SELECT
alt_item_id1, COUNT(*) AS dupeCount
FROM
item_master
WHERE
owner_id = 'GIII' AND alt_item_id1 <> ''
GROUP BY
alt_item_id1
HAVING
COUNT(*) > 1) oc ON o.alt_item_id1 = oc.alt_item_id1
WHERE
owner_id = 'GIII' AND o.alt_item_id1 <> ''
ORDER BY
alt_item_id1, if_updatestamp ASC
Not sure how to update the oldest record of every set of duplicate alt_item_id1
I am using SQL Server 2012
Any help is greatly appreciated!
To get the newest row to update, use the max of the if_updatestamp. for the oldest use the min. Then join it to your table for the udpate like so...
update IM
Set IM.im_cust9 = NewDupeRow.alt_item_id1
From item_master IM
JOIN (
SELECT alt_item_id1,Max(if_updatestamp) MaxUpdateValue
FROM item_master WHERE owner_id='GIII' AND alt_item_id1<>''
GROUP BY alt_item_id1 ) NewDupeRow
On IM.alt_item_ID = NewDupeRow.alt_item_ID
AND IM.if_updatedstamp = NewDupeRow.MaxUpdateValue
You can do this using an updatable CTE and row_number():
with toupdate as (
select i.*,
row_number() over (partition by alt_item_id order by if_updatestamp) as seqnum
from item_master i
)
update toupdate
set im_cust9 = alt_item_id1
where seqnum = 1;

sql query - update fields in existing with record values in the same table

Environment: SQL Server 2012
I have a transaction table that contains a group of records with group id column.
In the example illustrated below, group 2 records were copied from group 1 records, Except for the sideId, sideSort, topId and topSort columns. Is there a way to cascade that down from group 1 to group 2 for just topSort and sideSort? The hard part is that topId and sideId aren't the same because of Identity fields in parent tables.
Here is a sqlfiddle of the example
You can do it this way. This is based on the assumption that you copy all the records for one group (#copiedFromGroupId) to another (#copiedToGroupId), i.e. that the ID's will be shifted by the number of records in the first group.
declare #copiedFromGroupId int = 1
declare #copiedToGroupId int = 2
declare #shift int
select #shift = (select max(id) from Tracker where GroupId = #copiedToGroupId)
- (select max(id) from Tracker where GroupId = #copiedFromGroupId)
UPDATE T1
SET
T1.TopSort = T2.TopSort,
T1.SideSort = T2.SideSort
FROM Tracker T1
INNER JOIN Tracker T2 ON T1.ID = T2.ID + #shift
Check this SQL Fiddle
This is based on the row_number over the ORDER of TopId and SortID columns:
update test
set test.topSort = mix.topSort, test.sideSort = mix.sideSort
from
(select a.groupid aGroupid, b.groupID, b.Id bID, a.topSort, a.sideSort
from (select groupid,
row_number() over(order by topID, sideId) rn,
topSort, sideSort,
id
from test where groupid=1) a
inner join
(select groupid,
row_number() over(order by topID, sideId) rn,
topSort, sideSort,
id
from test where groupid=2) b ON a.rn = b.rn) mix
inner join test on test.id=mix.bId
WHERE test.groupid=2;
SQLFiddle
Assuming that Id is an order field in the Group:
WITH C as
(
select Tracker.*,
ROW_NUMBER() OVER (PARTITION BY GroupId ORDER BY Id) as RN
FROM Tracker
)
UPDATE CT
SET CT.topSort=CTU.topSort,
CT.sideSort=CTU.sideSort
FROM C as CT
JOIN C as CTU ON (CT.rn=CTU.rn)
and (CTU.GroupID=1)
WHERE CT.GroupID=2
SQLFiddle demo

update table where there is duplicate records using sql

i am trying to update a table but my problem is the target table has duplicate records so my update is failing for that reason. This is the error: attempt to update a target row with values from multiple join rows. I know when updating a table, we have to join unique keys but i cannot delete the duplicates from the table so i am looking for a work around for my situation. The CUSTOMERTABLE is the one that has the duplicates. Here is my query:
UPDATE CUSTOMERTABLE
SET SERVICE = 'BILLING'
FROM
(SELECT distinct(CUSTOMER_ID)AS ACCT_ID
,ED.CUSTOMER_NAME
, ED.CUSTOMER_ADDRESS
FROM CUSTOMER_RELATION ED, STG_CUSTOMER_REV TXN
WHERE ED.CUSTOMER_ID = TXN.CUS_ID
)AS X
WHERE X.ACCT_ID = CUSTOMERTABLE.ACCOUNT_NUMBER;
Try writing it with an IN clause:
UPDATE CUSTOMERTABLE
SET SERVICE = 'BILLING'
WHERE CUSTOMERTABLE.ACCOUNT_NUMBER IN
(SELECT CUSTOMER_ID
FROM CUSTOMER_RELATION ED
JOIN STG_CUSTOMER_REV TXN ON ED.CUSTOMER_ID = TXN.CUS_ID)
Here is another option, which probably has a better performance compared to an IN solution if CUSTOMER_RELATION or STG_CUSTOMER_REV are large tables.
UPDATE C
SET SERVICE = 'BILLING'
FROM CUSTOMERTABLE C
WHERE EXISTS (SELECT 1
FROM CUSTOMER_RELATION ED, STG_CUSTOMER_REV TXN
WHERE ED.CUSTOMER_ID = TXN.CUS_ID AND CUSTOMER_ID = C.ACCOUNT_NUMBER);
Try grouping on the CustomerId
UPDATE CUSTOMERTABLE
SET SERVICE = 'BILLING'
FROM
(SELECT distinct(CUSTOMER_ID)AS ACCT_ID
,ED.CUSTOMER_NAME
, ED.CUSTOMER_ADDRESS
FROM CUSTOMER_RELATION ED, STG_CUSTOMER_REV TXN
WHERE ED.CUSTOMER_ID = TXN.CUS_ID
GROUP BY ED.CUSTOMER_ID
)AS X
WHERE X.ACCT_ID = CUSTOMERTABLE.ACCOUNT_NUMBER;
You need to make sure that your select return non duplicates. Try using that select without the update statement and check if the select cotains the duplicates you want to get rid off.