UPDATE statement not working for certain columns in SQL Sever - sql

I had an update statment in a stored proc. which was not updating any records. Hence I broke the update statement into two parts as mentioned below -
the first update runs successfully but the second update is not updating any tax_id record with the same join condition and matches. I am not sure if the issue is with IN operator usage in the CASE statement or whatnot. Can anybody help?
UPDATE s
SET s.is_updated = '1'
,s.update_dt = GETDATE()
,s.update_source = 'ECM'
,s.party_type =
CASE
WHEN e.ClassificationType is not null THEN e.ClassificationType
ELSE s.party_type
END
FROM staging_cust_acct s
right join MTB_AML.dbo.tb_party_kyc e
on s.party_key = e.CustomerInternalID
UPDATE s
SET s.is_updated = '1'
,s.update_dt = GETDATE()
,s.update_source = 'ECM'
,s.tax_id =
case
when s.party_type IN ('Individual-Retail','Individual-High Net Worth') then e.TaxIndividualID
when s.party_type IN ('Corp-Publicly Traded','FI-MSB'
,'Corp-NFP/NGO','Corp-Personal/Non-Operating (WHV)'
,'Corp-Not Publicly Traded/Operating')
then e.TaxEntitiesID
when s.party_type = 'Government' then null
else s.tax_id end
FROM staging_cust_acct s
right join MTB_AML.dbo.tb_party_kyc e
on s.party_key = e.CustomerInternalID

I was trying to update the table on LEFT side of the join using the RIGHT join. Converting the join to LEFT OUTER JOIN worked fine. Moral of the story - Never use RIGHT join :)
UPDATE s
SET s.is_updated = '1'
,s.update_dt = GETDATE()
,s.update_source = 'ECM'
,s.tax_id =
case
when s.party_type IN ('Individual-Retail','Individual-High Net Worth') then e.TaxIndividualID
when s.party_type IN ('Corp-Publicly Traded','FI-MSB'
,'Corp-NFP/NGO','Corp-Personal/Non-Operating (WHV)'
,'Corp-Not Publicly Traded/Operating')
then e.TaxEntitiesID
when s.party_type = 'Government' then null
else s.tax_id end
FROM staging_cust_acct s
left outer join MTB_AML.dbo.tb_party_kyc e
on s.party_key = e.CustomerInternalID

Related

Case in update statement

I am trying to translate a talend code which has a nested IF statement into SQL
I thought I had translated it correctly, but no records are getting updated since the join condition fails. I added a top level case statement to check for existence of records, but wanted to double check from the experts here if my translation is correct at all.
Logic from Talend Mapper:
IF row32.DISPLAY_NAME_REPORTED IS NULL THEN
IF row31.REPORTED_DISPLAY_NAME IS NULL THEN
IF row87.SPEC_TYPE1 IS NULL THEN
IF row87.SPEC_TYPE2 IS null THEN
row34.Series
ELSE
row34.Series + row34.Type2
END
ELSE
row34.Series + row34.Type2
END
ELSE
row31.REPORTED_DISPLAY_NAME
END
ELSE
row32.DISPLAY_NAME_REPORTED
END
Corresponding case statement in SQL:
update a
set a.seriesbt = case when exists (select 1 from row32 x where
x.delivery_fk = a.delivery_fk) then
case when b.delivery_fk is not null and
b.DISPLAY_NAME_REPORTED is null then
case when c.reported_display_name is null then
case when d.SPEC_TYPE1 is null then
case when d.SPEC_TYPE2 is null then
a.series
else
a.series+a.SPEC_TYPE2 end
else a.series + a.SPEC_TYPE1 end
else c.reported_display_name end
else b.DISPLAY_NAME_REPORTED end
else a.series end
from tmpSales a
left join row32 b on b.delivery_fk = a.delivery_fk
left join row31 c on c.DELIVERY_FK = a.delivery_fk
left join row87 d on d.DELIVERY_FK = a.delivery_fk
Question is: Did I translate the talend mapper logic into SQL correctly? If not, can you please tell me what is wrong.
Should I be include "when exists" for each table?
I thought the left join should implicitly handle it.
You seem to have added an additional condition that was not in your original code. Coding the opposite way can make things simpler and avoid nested CASE expressions.
I changed your table alias to make it easier to understand where the columns come from without having to go back to the FROM clause.
UPDATE s
SET a.seriesbt = CASE WHEN r32.DISPLAY_NAME_REPORTED IS NOT NULL THEN r32.DISPLAY_NAME_REPORTED
WHEN r31.reported_display_name IS NOT NULL THEN r31.reported_display_name
WHEN r87.SPEC_TYPE1 IS NOT NULL THEN s.series /*row34.Series*/ + s.SPEC_TYPE1
WHEN r87.SPEC_TYPE2 IS NULL THEN s.series --row34.Series
ELSE s.series /*row34.Series*/ + s.SPEC_TYPE2
END
FROM tmpSales s
LEFT JOIN row32 r32 ON r32.delivery_fk = s.delivery_fk
LEFT JOIN row31 r31 ON r31.DELIVERY_FK = s.delivery_fk
LEFT JOIN row87 r87 ON r87.DELIVERY_FK = s.delivery_fk;
I just realized that it could be simplified even more.
UPDATE s
SET a.seriesbt = COALESCE( r32.DISPLAY_NAME_REPORTED,
r31.reported_display_name,
s.series /*row34.Series*/ + s.SPEC_TYPE1,
s.series /*row34.Series*/ + s.SPEC_TYPE2,
s.series --row34.Series
)
FROM tmpSales s
LEFT JOIN row32 r32 ON r32.delivery_fk = s.delivery_fk
LEFT JOIN row31 r31 ON r31.DELIVERY_FK = s.delivery_fk
LEFT JOIN row87 r87 ON r87.DELIVERY_FK = s.delivery_fk;

SQL avoid 0 in the calculation

Can anyone help me try to solve this equation? The "Lost_Weight" is a calculation field and I'm trying to get the result of HWeight - renWeight = '0' if the renWeight is 0. The where clause has a controversial statement that put a Challenge to me to make that happen. See below.
SELECT TOP (100) PERCENT dbo.Name.ID,
dbo.Name.CO_ID,
dbo.Name.FULL_NAME,
dbo.Name.STATE_PROVINCE, dbo.Tops_Profile.START_WGHT,
dbo.Tops_Profile.RENEWAL_WEIGHT,
dbo.Tops_Profile.H_WEIGHT - dbo.Tops_Profile.RENEWAL_WEIGHT AS Lost_Weight,
dbo.Tops_Profile.H_WEIGHT,
dbo.Name.JOIN_DATE,
dbo.Name.BIRTH_DATE,
RIGHT(dbo.TOPS_AWARDS.AWARD_TYPE, 15) AS AWARDS_TYPE,
dbo.TOPS_AWARDS.AWARD_CATEGORY,
dbo.TOPS_AWARDS.AWARD_DATE,
dbo.vw_RegDirs.TARGET_ID AS
RD_ID,
dbo.vw_Coords.TARGET_ID AS Coord_ID,
dbo.vw_Coords.FULL_NAME AS
Coord_Name,
dbo.vw_AreaCapts.TARGET_ID AS AC_ID, dbo.Name.STATUS
FROM dbo.Name INNER JOIN dbo.Tops_Profile
ON dbo.Name.ID = dbo.Tops_Profile.ID
INNER JOIN dbo.vw_RegDirs
ON dbo.Name.CO_ID = dbo.vw_RegDirs.CHAPTER
INNER JOIN dbo.vw_Coords
ON dbo.Name.CO_ID = dbo.vw_Coords.CHAPTER
INNER JOIN dbo.vw_AreaCapts
ON dbo.Name.CO_ID = dbo.vw_AreaCapts.CHAPTER
LEFT OUTER JOIN dbo.TOPS_AWARDS
ON dbo.Name.ID = dbo.TOPS_AWARDS.ID
WHERE (dbo.Tops_Profile.RENEWAL_WEIGHT <> '0')
AND (dbo.Name.STATUS = 'a')
AND (dbo.Tops_Profile.H_WEIGHT - dbo.Tops_Profile.RENEWAL_WEIGHT >= 100')
OR (dbo.Name.STATUS = 'a') AND (dbo.TOPS_AWARDS.AWARD_TYPE LIKE '%Century%')
right now if the renewal_weight is 0 it automatically give me the number from the H_WEIGHT in the Lost_Weight field and I need the result to be 0 if the RENEWAL_WEIGHT is 0.
I'm guessing 0 is a special value in this situation. This can be fixed by using CASE
Replace
dbo.Tops_Profile.H_WEIGHT - dbo.Tops_Profile.RENEWAL_WEIGHT AS Lost_Weight
With
CASE WHEN RENEWAL_WEIGHT = 0 THEN 0
ELSE dbo.Tops_Profile.H_WEIGHT - dbo.Tops_Profile.RENEWAL_WEIGHT
END AS Lost_Weight

Join tables and groupby results based on user defined parameters in sql server 2008

I want to join two tables and group by the result based on a user defined parameter in Sql Server 2008. I tried the query below but it is not working. I appreciate if someone helps me to see my mistake and correct it for me. Regards.
Select TotalVolume= SUM(volume),
PrimGroup = r.PrimaryGroup, SnGroup = r.SecondaryGroup
from Requests r
inner join #Calculations c on
case #PrimaryId is not null then c.PrimaryGroup = r.PrimaryGroup end
and case #SecondaryId is not null then c.SecondaryGroup = r.SecondaryGroup end
and c.SrgId = r.SrgId
group by
case #PrimaryId is not null then r.PrimaryGroup end,
case #SecondaryId is not null then r.SecondaryGroup end
Try this:
Select TotalVolume= SUM(volume),
PrimGroup = r.PrimaryGroup, SnGroup = r.SecondaryGroup
from Requests r
inner join #Calculations c on
((#PrimaryId is null) or
(#PrimaryId is not null) and c.PrimaryGroup = r.PrimaryGroup)
and ((#SecondaryId is null) or
(#SecondaryId is not null) and c.SecondaryGroup = r.SecondaryGroup)
and c.SrgId = r.SrgId
group by
case when #PrimaryId is not null then r.PrimaryGroup end,
case when #SecondaryId is not null then r.SecondaryGroup end

Stored procedure: how can I set a field value in the returned data without changing the tables it came from?

SELECT
EQ.EventQuestId,
EQ.QuestionText,
EQ.HelpText,
EQ.EventQuestOptType,
EQ.DisplayOrder AS QuestDisplayOrder,
EQO.EventQuestOptId,
EQO.OptionText,
EQO.IsOtherSpecify,
STJC.STJCategory,
EQO.DisplayOrder AS OptDisplayOrder,
EA.EventId, EA.AnswerText
FROM EventQuest EQ
INNER JOIN EventQuestOpt EQO
ON EQ.EventQuestId = EQO.EventQuestId
LEFT JOIN EventAnswer EA
ON EA.EventQuestId = EQ.EventQuestId
AND EA.EventQuestOptId = EQO.EventQuestOptId
AND EventId = #EventId
LEFT JOIN dbo.STJCategories STJC
ON STJC.STJID = EQO.STJID
WHERE EQO.Status <> 'false'
ORDER BY EQ.DisplayOrder, EQO.DisplayOrder
I have this in my stored proc. I want to set the EQ.QuestionText to the STJC.STJCategory value wherever EQ.QuestionText = "example". I just want this in the returned result, not in table it came from. How do I go about this as I've never tried to do this before and have no clue where to begin with that, if it's possible.
I hope this makes sense.
You can use case for that:
select case
when EQ.QuestionText = 'example' then STJC.STJCategory
else EQ.QuestionText
end as QuestionText
use a CASE statement
SELECT
EQ.EventQuestId,
CASE EQ.QuestionText WHEN 'example'
THEN STJC.STJCategory ELSE EQ.QuestionText END QuestionText ,
EQ.HelpText,
EQ.EventQuestOptType,
EQ.DisplayOrder AS QuestDisplayOrder,
EQO.EventQuestOptId,
EQO.OptionText,
EQO.IsOtherSpecify,
STJC.STJCategory,
EQO.DisplayOrder AS OptDisplayOrder,
EA.EventId, EA.AnswerText
FROM EventQuest EQ
INNER JOIN EventQuestOpt EQO
ON EQ.EventQuestId = EQO.EventQuestId
LEFT JOIN EventAnswer EA
ON EA.EventQuestId = EQ.EventQuestId
AND EA.EventQuestOptId = EQO.EventQuestOptId
AND EventId = #EventId
LEFT JOIN dbo.STJCategories STJC
ON STJC.STJID = EQO.STJID
WHERE EQO.Status <> 'false'
ORDER BY EQ.DisplayOrder, EQO.DisplayOrder

Extracting null fields in SQL Server

I will try to be as detailed as possible. Our corporate controller has asked me for some information regarding our suppliers. Here are the tables:
spp = supplier table, each supplier has one record, there are 5,222 records
ast = supplier account profile, there is a (M, 1) relationship between this table and spp, there are 8,950 records in this table. Each duplicate spp_id has a different atp_id which is a transaction profile.
crt = bank account information, a supplier may or may not have bank account info
xvd = table of checking tables, xvd.xcd_id is the field that holds the checking table id. Checking table 0007 is the table that contains the discount info.
Here is my script:
select spp.spp_id supp_num,
spp.spp_matchname supp_name,
case when spp.spp_ddcalculation = 0
then 'End of Month'
else
case when spp.spp_ddcalculation = 1
then 'Net'
else
case when spp.spp_ddcalculation = 2
then 'End of 10, 20, 30'
else
case when spp.spp_ddcalculation = 3
then 'End of 15 or 30'
else null
end
end
end
end calculation1,
convert(varchar(2), spp.spp_ddduration) + case when spp.spp_ddmd = 0
then ' Days'
else case when spp.spp_ddmd = 1
then ' Months'
else null
end
end duration1,
spp.spp_ddday stop_day1,
xvd.xvd_desc discount,
crt.crt_name bank,
case when ast.ast_ddcalculation = 0
then 'End of Month'
else
case when ast.ast_ddcalculation = 1
then 'Net'
else
case when ast.ast_ddcalculation = 2
then 'End of 10, 20, 30'
else case when ast.ast_ddcalculation = 3
then 'End of 15 or 30'
else null
end
end
end
end
calculation2,
convert(varchar(2), ast.ast_ddduration) + case when ast.ast_ddmd = 0
then ' Days'
else case when ast.ast_ddmd = 1
then ' Months'
else null
end
end
duration2,
ast.ast_ddday stop_day2
from spp left join ast on spp.spp_id = ast.spp_id
left join crt on ast.crt_id = crt.crt_id
inner join xvd on ast.cfd_id = xvd.xcv_id
where xvd.xcd_id = '0007'
and xvd.lng_id = 0
order by spp.spp_id
The problem is that there are 371 records in the ast table that have a non null cfd_id which is the field that relates to the discount in checking table 0007. When I run this I get 371 records, but I need all suppliers, even those with null discounts. I know the problem is a combination of my joins and the fact that there is not a null xcv_id in checking table 0007. Can anyone see anything glaring that I have overlooked?
To recap, there are 8,950 records in ast, but only 371 of them have a non null cfd_id. I need to grab all 8,950 records, I can't seem to extract the null discounts. I think I can probably pull everything into a temp table then grab the discounts, but am wondering if there is a way to do this in one select statement.
Thanks
Tony
Edit: The last line of my from statement seems to be the primary issue
inner join xvd on ast.cfd_id = xvd.xcv_id
There are no null xcv_id but there are null cfd_id. Is there another way to join those two tables, besides checking for equality?
Forgot to mention, we are on SQL Server 2008 R2.
Does this solve the problem ?
FROM spp
LEFT JOIN ast
ON spp.spp_id = ast.spp_id
LEFT JOIN crt
ON ast.crt_id = crt.crt_id
INNER JOIN xvd
ON xvd.xcv_id = ast.cfd_id
WHERE xvd.xcd_id = '0007'
AND xvd.lng_id = 0
I think you can just change your inner join to a left join:
from spp left join ast on spp.spp_id = ast.spp_id
left join crt on ast.crt_id = crt.crt_id
inner join xvd on ast.cfd_id = xvd.xcv_id
to
from spp left join ast on spp.spp_id = ast.spp_id
left join crt on ast.crt_id = crt.crt_id
left join xvd on ast.cfd_id = xvd.xcv_id
If you are saying that you want to select records where xvd.xcd_id is 0007 or null then change your where clause to this:
(xvd.xcd_id = '0007' OR xvd.xcd_id is null)
This sounds like a perfect use for views. Instead of trying to build one complex query, you could build a series of views that build upon one another filtering the data the way you want it... then apply the final query to the last view.