Trying to update a field conditionally in SQL Stored Procedure - sql

I have a procedure that populates two sets of application information into the same fields. First the fields are filled out with applicable accounts from group "A" and then the same process happens for group "B" accounts.
Most of the group B fields are filled in by a insert/select statement. However, the query to select "account number" is a little more complex and that is in an UPDATE statement. I will paste the code below but I cannot get it to properly update the rows (for group B) with account numbers, despite the fact the query works on its own outside the procedure (essentially, the account numbers do exist).
Any idea why? I tried adding a case statement to single out group B rows (the where clause is hardcoded for group B... e.g. clfcode = 3) but that didn't work. Let me know if you need more information. I haven't much experience with update statements in stored procedures.
update src
set account_key = case when src.clfcode = 3 and src.branch_key = 12 then a.account_key else src.account_key end
from #src_table src
inner join SDFDW_Landing.cu.FICS_ms_Investor_Loan l
on l.loan_id = src.application_number
left join dm.dim_product p
on p.product_key = src.product_key
left join (
Select Distinct t.PARENTACCOUNT, t.USERCHAR1 as loan_id
from SDFDW_Landing.dbo.tracking t
where t.TYPE = 1
and t.ProcessDate = #v_max_last_processed_date
and t.USERCHAR1 is not null
) t on t.loan_id = l.loan_id
left join dm.dim_account a
on t.PARENTACCOUNT = a.account_nkey
WHERE p.bdw_report_category = 'Mortgage'
and l.processdate = #v_max_last_processed_date

The join on a subquery might cause the issue. You could try to replace it with an apply and see if that helps.
update
src
set
account_key =
case
when
src.clfcode = 3
and src.branch_key = 12
then
a.account_key
else
src.account_key
end
from
#src_table src
inner join
SDFDW_Landing.cu.FICS_ms_Investor_Loan l
on l.loan_id = src.application_number
left join
dm.dim_product p
on p.product_key = src.product_key
outer apply (
Select
acc.*
from
dm.dim_account acc
inner join
SDFDW_Landing.dbo.tracking t
on acc.account_nkey = t.parentaccount
where
t.TYPE = 1
and t.ProcessDate = #v_max_last_processed_date
and t.USERCHAR1 is not null
and t.loan_id = l.loan_id
) a
WHERE
p.bdw_report_category = 'Mortgage'
and l.processdate = #v_max_last_processed_date
alternatively since you are already within a stored procedure, I'd populate a temp table with the data from your subquery and simply join on that temp table from your update statement.

Related

SQL Oracle Update containing left join

I want to perform an update for the results of a select query.
SELECT
a.reason,
n.note
FROM applications a
LEFT JOIN notes n on n.app_id = a.app_id
AND n.note LIKE '%old%'
WHERE a.code = 'run' AND a.reason IS NULL
I thought I could perform these updates separately wrapping the select in an update however I get the error ORA-01733: virtual column not allowed here. How can I go about performing these updates?
UPDATE (
SELECT
a.reason AS Reason
FROM applications a
LEFT JOIN notes n on n.app_id = a.app_id
AND n.note LIKE '%old%'
WHERE a.code = 'run' AND a.reason IS NULL
) SET Reason = null
UPDATE (
SELECT
n.note AS Note
FROM applications a
LEFT JOIN notes n on n.app_id = a.app_id
AND n.note LIKE '%old%'
WHERE a.code = 'run' AND a.reason IS NULL
) SET Note = null
You can't update the two tables at the same time. You need two different update statements as follows:
Updating the APPLICATIONS table is quite easy as all the records of the APPLICATIONS table having a.code = 'run' AND a.reason IS NULL will be there in your SELECT query.
UPDATE APPLICATIONS A
SET
REASON = NULL
WHERE A.CODE = 'run'
AND A.REASON IS NULL;
To update the NOTES table, you can use the EXISTS clause as follows:
UPDATE NOTES N
SET
NOTE = NULL
WHERE EXISTS (
SELECT 1
FROM APPLICATIONS A
WHERE N.APP_ID = A.APP_ID
AND A.CODE = 'run'
AND A.REASON IS NULL
)
AND N.NOTE LIKE '%old%'
You must update the NOTES table first and then APPLICATIONS table as while updating the NOTES table you are using the condition A. REASON IS NULL but while updating the APPLICATIONS table, you are updating the REASON column.

In a stored procedure how can you loop table A and then update table B

Within a stored procedure I need to loop the following table:
SELECT *
FROM dbo.UsersInRoles
INNER JOIN Application_Users ON UsersInRoles.AppUserID = Application_Users.AppUserID
WHERE (UsersInRoles.ApplicationId = #ApplicationId)
AND (UsersInRoles.RoleId = #CurrentRoleId)
AND (Application_Users.LastLogin < #StartDate)
And for each record that is looped I need to perform this update:
UPDATE UsersInRoles
SET UsersInRoles.RoleId = #DenyRoleId
WHERE (UsersInRoles.ApplicationId = #ApplicationId)
AND (UsersInRoles.RoleId = #CurrentRoleId)
If there is a better way to perform this then I'm open to suggestions. Basically the 1st query does a filter based upon the INNER JOIN to determine which records need to be updated. Then those filtered records are looped and updated with a new RoleID.
Update with join:
UPDATE UIR
SET UIR.RoleId = #DenyRoleId
FROM UsersInRoles UIR
INNER JOIN Application_Users ON UIR.AppUserID = Application_Users.AppUserID
WHERE (UIR.ApplicationId = #ApplicationId)
AND (UIR.RoleId = #CurrentRoleId)
AND (Application_Users.LastLogin < #StartDate)
You can use a CTE to do the UPDATE:
;WITH ToUpdate AS (
SELECT uir.RoleId
FROM dbo.UsersInRoles AS uir
INNER JOIN Application_Users AS au
ON uir.AppUserID = au.AppUserID
WHERE (uir.ApplicationId = #ApplicationId) AND
(uir.RoleId = #CurrentRoleId) AND
(au.LastLogin < #StartDate)
)
UPDATE ToUpdate
SET RoleId = #DenyRoleId
So, you just type wrap the query in a CTE and then perform the UPDATE on the table returned by the CTE. The RoleId value will be propagated to the records of the actual table, UsersInRoles.

SQL: Want to alter the conditions on a join depending on values in table

I have a table called Member_Id which has a column in it called Member_ID_Type. The select statement below returns the value of another column, id_value from the same table. The join on the tables in the select statement is on the universal id column. There may be several entries in that table with this same universal id.
I want to adjust the select statement so that it will return the id_values for entries that have member_id_type equal to '7'. However if this is null then I want to return records that have member_id_type equal to '1'
So previously I had a condition on the join (commented out below) but that just returned records that had member_id_type equal to '7' and otherwise returned null.
I think I may have to use a case statement here but I'm not 100% sure how to use it in this scenario
SELECT TOP 1 cm.Contact_Relation_Gid,
mc.Universal_ID,
mi.ID_Value,
cm.First_Name,
cm.Last_Name,
cm.Middle_Name,
cm.Name_Suffix,
cm.Email_Address,
cm.Disability_Type_PKID,
cm.Race_Type_PKID,
cm.Citizenship_Type_PKID,
cm.Marital_Status_Type_PKID,
cm.Actual_SSN,
cm.Birth_Date,
cm.Gender,
mc.Person_Code,
mc.Relationship_Code,
mc.Member_Coverage_PKID,
sc.Subscriber_Coverage_PKID,
FROM Contact_Member cm (NOLOCK)
INNER JOIN Member_Coverage mc (NOLOCK)
ON cm.contact_relation_gid = mc.contact_relation_gid
AND mc.Record_Status = 'A'
INNER JOIN Subscriber_Coverage sc (NOLOCK)
ON mc.Subscriber_Coverage_PKID = sc.Subscriber_Coverage_PKID
AND mc.Record_Status = 'A'
LEFT outer JOIN Member_ID mi ON mi.Universal_ID = cm.Contact_Gid
--AND mi.Member_ID_Type_PKID='7'
WHERE cm.Contact_Relation_Gid = #Contact_Relation_Gid
AND cm.Record_Status = 'A'
Join them both, and use one if the other is not present:
select bt.name
, coalesce(eav1.value, eav2.value) as Value1OrValue2
from BaseTable bt
left join EavTable eav1
on eav1.id = bt.id
and eav1.type = 1
left join EavTable eav2
on eav2.id = bt.id
and eav2.type = 2
This query assumes that there is never more than one record with the same ID and Type.

SQL update with count gets only nulls

I am using SQL Server 2008 R2 and SSRS 2008 to generate the report. I am trying to update a table to get a count of the results from another table.
UPDATE r
SET r.Race = d2.Race,
r.RaceNum = d2.count
FROM #results r
INNER JOIN
(SELECT d.Race,
COUNT(d.race) AS 'count'
FROM #Demographic d
GROUP BY d.Race)d2 ON r.Race = d2.Race
An insert works perfectly but I am inserting several times into the results table to create a demographics report. This is creating a lot Null data at the table of the results. If anyone has an idea of what I am going wrong the help would be appreciated.
Not certain, but first guess is that count is a reserved word... change it to something else such as...
update r
set r.Race = d2.Race, r.RaceNum = d2.cnt
from #results r
inner join
(select d.Race, COUNT(d.race) as 'cnt' from #Demographic d group by d.Race)d2
on r.Race = d2.Race
or alternatively try delimiting the column identifier as [count] or if you have quoted identifiers on "count"
Your query is:
update r
set r.Race = d2.Race, /*<---------*/
r.RaceNum = d2.count
from #results r inner join
(select d.Race, COUNT(d.race) as 'count'
from #Demographic d
group by d.Race
) d2
on r.Race = d2.Race /*<-------- */
The two marked lines stand out. You are joining on values using =, then you are setting one equal to the other. This may not be the problem, but it is suspicious. If you are joining on them, why are you setting them equal? My suspicion is that the join is failing, because nothing matches it.
You don't need to update the race column, since that's the equality portion of your join.
As written, any race not in #demographic would have its racenum set to null. If you want 0 for those try:
UDPATE
r
SET
r.RaceNum = ISNULL(d2.ct, 0)
FROM #results r
LEFT JOIN
(
SELECT
d.Race
, COUNT(d.race) as ct
FROM
#Demographic d
GROUP BY
d.Race
) d2
ON
r.Race = d2.Race

Viewing records in a Row in a column from the same Table

I am crating a view to display records with contract dates in them.
The data for this view comes from two tables, one which stores the client details and another which stores the date info.
The dates themeselves are stored in the DateCol column and the ID for the DateCol column comes from TypeID eg 118 equals a Contract Start Date and 119 equals an End date.
This returns about 250 results.
The view I have built runs a lookup against the client id and shows the date from the date_type(ie 118 and 119 shows 01/01/2012 and 01/03/2012). If I add a third column that shows me 120, the total number of results is reduced to 6.
I need to see all the results but im not sure how to build a view that shows all of these. I cant modify the original database as it is a backed for Maximizer.
We are using SQL 2005 and I have built this using the Management STudio but my knowledge is a bit limited.
This is the code for my view:
SELECT *
FROM dbo.AMGR_Client_Tbl
INNER JOIN dbo.FOOTPRINTS_Companies_118
ON dbo.AMGR_Client_Tbl.Client_Id =
dbo.FOOTPRINTS_Companies_118.Client_Id
INNER JOIN dbo.FOOTPRINTS_Companies_119
ON dbo.AMGR_Client_Tbl.Client_Id =
dbo.FOOTPRINTS_Companies_119.Client_Id
INNER JOIN dbo.FOOTPRINTS_Companies_120
ON dbo.AMGR_Client_Tbl.Client_Id =
dbo.FOOTPRINTS_Companies_120.Client_Id
INNER JOIN dbo.FOOTPRINTS_Companies_121
ON dbo.AMGR_Client_Tbl.Client_Id =
dbo.FOOTPRINTS_Companies_121.Client_Id
WHERE ( dbo.AMGR_Client_Tbl.Record_Type = '1' ) AND ( dbo.AMGR_Client_Tbl.Name_Type = 'C' )
OR ( dbo.AMGR_Client_Tbl.Record_Type = '1' ) AND ( dbo.AMGR_Client_Tbl.Name_Type = 'C' )
Ok, First of all you should list the actual column names that you need on your view and not use *. I believe that you just need to change the INNER JOINs for LEFT JOINs. So it would be like this:
SELECT [List Your Columns Here]
FROM dbo.AMGR_Client_Tbl
LEFT JOIN dbo.FOOTPRINTS_Companies_118
ON dbo.AMGR_Client_Tbl.Client_Id =
dbo.FOOTPRINTS_Companies_118.Client_Id
LEFT JOIN dbo.FOOTPRINTS_Companies_119
ON dbo.AMGR_Client_Tbl.Client_Id =
dbo.FOOTPRINTS_Companies_119.Client_Id
LEFT JOIN dbo.FOOTPRINTS_Companies_120
ON dbo.AMGR_Client_Tbl.Client_Id =
dbo.FOOTPRINTS_Companies_120.Client_Id
LEFT JOIN dbo.FOOTPRINTS_Companies_121
ON dbo.AMGR_Client_Tbl.Client_Id =
dbo.FOOTPRINTS_Companies_121.Client_Id
WHERE ( dbo.AMGR_Client_Tbl.Record_Type = '1' ) AND ( dbo.AMGR_Client_Tbl.Name_Type = 'C' )
OR ( dbo.AMGR_Client_Tbl.Record_Type = '1' ) AND ( dbo.AMGR_Client_Tbl.Name_Type = 'C' )
Also, you should note that on your WHERE there seems to be a duplicated condition.