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

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

Related

How to do inner join in Vertica Update?

I was trying to do a inner join with 3 tables in a update query. I tried to find the solution in multiple sites but didn't get the solution.
Following a sample query I am trying:
UPDATE TGT
SET C1 = CASE WHEN TGT.c2 = SRC.c2 AND SRC.C3 = 'P' THEN SRC.C1 ELSE NULL END,
C2 = CASE WHEN TGT.c2 = SRC.c2 AND SRC.C3 = 'D' THEN SRC.C1 ELSE NULL END
FROM SRC
INNER JOIN SRC1
ON SRC.C9 = SRC1.C9
AND SRC.C9 = TGT.C9;
Thanks in Advance!!
I would expect your syntax to work. (I don't have Vertica handy but its query parser is based on Postgres.)
Perhaps -- unlike Postgres -- JOIN is not allowed in the FROM. Then you can put the join conditions in the WHERE clause:
UPDATE TGT
SET C1 = (CASE WHEN TGT.c2 = SRC.c2 AND SRC.C3 = 'P' THEN SRC.C1 END)
C2 = (CASE WHEN TGT.c2 = SRC.c2 AND SRC.C3 = 'D' THEN SRC.C1 END)
FROM SRC, SRC1
WHERE SRC.C9 = SRC1.C9 AND SRC.C9 = TGT.C9;

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

UPDATE statement not working for certain columns in SQL Sever

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

UDF not returning the same value as select contained in UDF

I created this UDF
CREATE FUNCTION [dbo].[HasExtendedRetentionSamples] (#BoxNumber varchar(20))
RETURNS int
AS
BEGIN
declare #cnt int
set #cnt = 0
select #cnt = (select count(*)
from tFreezerBoxInfo bi
inner join tFreezerDetails fd on fd.boxTrayId = bi.boxTrayId
inner join tncDrugTestListNew dt on dt.labnumber = fd.labnumber
inner join ExtendedRetentionSites a on dt.number = a.number
where boxnumber = 'ND011811001'
and
case isnull([retention],0)
when 0 then proposedDestructionDate
else dateadd(dd,abs([retention]),proposedDestructionDate)
end <> proposedDestructionDate)
return #cnt
END
When I execute the UDF
select dbo.[HasExtendedRetentionSamples] ('ND011811001')
The value 0 is returned, which is incorrect,
When I execute the SQL statement contained in the UDF (replacing #BoxNumber with 'ND011811001')...
select count(*)
from tFreezerBoxInfo bi
inner join tFreezerDetails fd on fd.boxTrayId = bi.boxTrayId
inner join tncDrugTestListNew dt on dt.labnumber = fd.labnumber
inner join ExtendedRetentionSites a on dt.number = a.number
where boxnumber = 'ND011811001'
and
case isnull([retention],0)
when 0 then proposedDestructionDate
else dateadd(dd,abs([retention]),proposedDestructionDate)
end <> proposedDestructionDate
The value 5 is returned, which is correct.
So the big question is WHY????
All the datatype in the joins & case statement are the same.
I would change the function to this, take the count out of the subquery:
CREATE FUNCTION [dbo].[HasExtendedRetentionSamples] (#BoxNumber varchar(20))
RETURNS int
AS
BEGIN
declare #cnt int
set #cnt = 0
select #cnt = count(*)
from tFreezerBoxInfo bi
inner join tFreezerDetails fd on fd.boxTrayId = bi.boxTrayId
inner join tncDrugTestListNew dt on dt.labnumber = fd.labnumber
inner join ExtendedRetentionSites a on dt.number = a.number
where boxnumber = 'ND011811001'
and
case isnull([retention],0)
when 0 then proposedDestructionDate
else dateadd(dd,abs([retention]),proposedDestructionDate)
end <> proposedDestructionDate
return #cnt
END
try changing your CASE statement to:
case
when isnull([retention],0) = 0 then proposedDestructionDate
else dateadd(dd,abs([retention]),proposedDestructionDate)
end <> proposedDestructionDate
I am embarrassed to say, I have found out why this was happening.....
When I created the table ExtendedRetentionSites, it was created & populated with me as the owner. I realized that and recreated the table with DBO as the owner, populating this table, but never dropping the table with the same name that I owned. I ran an insert statement & it inserted into ExtendedRetentionSites that I owned, but this data never made it to the table that DBO owned.
Soooooo when I ran the select script, it used ExtendedRetentionSites that I owned, that had the new row, that would give me the results I was looking for. When I ran the UDF, it used the table that DBO owned, without the new row thus returning nothing or a zero count.
Thanks to everyone who helped me out with this, I will now pull my head out of my ass & get back to work.
Thanks again to all!!!!

SQL SP runs Slow

Hi
I am using an SP which takes 7 minutes in a server which has 7336 recrds
and 6seconds in another server which has 3500 records.
Can anybody help me to know why is it happening?
Thanks,
-Divya
THE SP:
SELECT WORKSHEET_ID
FROM PERSON PER
INNER JOIN PERSON EMPLEE
ON EMPLEE.PERSON_ID = PER.PERSON_ID
AND
dbo.FN_CHECKRPTSECURITY(EMPLEE.PERSON_ID, #p_SEC_ACCOUNT_ID) > 0
LEFT JOIN SEARCH_ASSIGNMENT_VW PERSON_ASGN
ON PERSON_ASGN.ASSIGNMENT_ID =
dbo.FN_GETRPTASSIGNMENTID(EMPLEE.PERSON_ID)
LEFT JOIN LOOKUP EMPLEE_ASGN_STAT
ON EMPLEE_ASGN_STAT.TYPE_ = 'ASSIGNMMENT_STATUS_CODE'
AND EMPLEE_ASGN_STAT.CODE = PERSON_ASGN.ASGN_STAT_CODE
INNER JOIN
(SELECT w1.ASSIGNMENT_ID, w1.WORKSHEET_ID, w1.EFFECTIVE_DATE, w1.APPROVED_BY, w3.CREATED_BY
FROM WORKSHEET_PAYROLL_VW w1
INNER JOIN WORKSHEET w3
ON w3.WORKSHEET_ID = w1.WORKSHEET_ID
WHERE w1.EFFECTIVE_DATE = CASE
WHEN #p_MOST_RECENT_ONLY = 'Y'
THEN (SELECT MAX(w2.EFFECTIVE_DATE)
FROM WORKSHEET_PAYROLL_VW w2
WHERE w1.ASSIGNMENT_ID = w2.ASSIGNMENT_ID
AND (ISNULL(#p_WKS_EFFECTIVE_DATE,w2.EFFECTIVE_DATE) =w2.EFFECTIVE_DATE))
ELSE ISNULL(#p_WKS_EFFECTIVE_DATE,w1.EFFECTIVE_DATE)
END
)
PERSON_WKS
ON PERSON_WKS.ASSIGNMENT_ID = dbo.FN_GETRPTASSIGNMENTID(EMPLEE.PERSON_ID)
INNER JOIN
(SELECT ASSIGNMENT_ID, VALUE
FROM ASSIGNMENT_HISTORY AH
WHERE FIELD_NAME ='HOME PAYROLL GROUP'
AND EFFECTIVE_DATE = (SELECT MAX(EFFECTIVE_DATE)
FROM ASSIGNMENT_HISTORY
WHERE ASSIGNMENT_ID = AH.ASSIGNMENT_ID
AND EFFECTIVE_DATE <=getDate()
AND FIELD_NAME = 'HOME PAYROLL GROUP')
)HOME_PAYROLL
ON HOME_PAYROLL.ASSIGNMENT_ID = dbo.FN_GETRPTASSIGNMENTID(EMPLEE.PERSON_ID)
WHERE
(#p_SELECTED_PERSON_ONLY = 'N' OR EMPLEE.PERSON_ID = #p_PERSON_ID)
AND
(#p_ASGN_STAT_CODE IS NULL OR PERSON_ASGN.ASGN_STAT_CODE = SUBSTRING(#p_ASGN_STAT_CODE,1,1)
OR PERSON_ASGN.ASGN_STAT_CODE = SUBSTRING(#p_ASGN_STAT_CODE,2,1))
AND
(#p_POLICY_ID IS NULL OR PERSON_ASGN.PROGRAM_CODE = #p_POLICY_ID)
AND
(#p_HOME_COUNTRY_ID IS NULL OR PERSON_ASGN.HOMECOUNTRYID=#p_HOME_COUNTRY_ID)
AND
(#p_HOME_CITY_ID IS NULL OR PERSON_ASGN.HOMECITYID=#p_HOME_CITY_ID )
AND
(#p_HOME_COMPANY_ID IS NULL OR PERSON_ASGN.HOMEBUSINESSID=#p_HOME_COMPANY_ID )
AND
(#p_HOME_DIVISION_ID IS NULL OR PERSON_ASGN.HOMECOMPONENTID=#p_HOME_DIVISION_ID )
AND
(#p_HOST_COUNTRY_ID IS NULL OR PERSON_ASGN.HOSTCOUNTRYID=#p_HOST_COUNTRY_ID )
AND
(#p_HOST_CITY_ID IS NULL OR PERSON_ASGN.HOSTCITYID=#p_HOST_CITY_ID )
AND
(#p_HOST_COMPANY_ID IS NULL OR PERSON_ASGN.HOSTBUSINESSID=#p_HOST_COMPANY_ID )
AND
(#p_HOST_DIVISION_ID IS NULL OR PERSON_ASGN.HOSTCOMPONENTID=#p_HOST_DIVISION_ID )
AND
(#p_CREATED_BY IS NULL OR PERSON_WKS.CREATED_BY=#p_CREATED_BY )
AND
(#p_APPROVED_BY IS NULL OR PERSON_WKS.APPROVED_BY=#p_APPROVED_BY )
AND
(#p_payroll_code IS NULL OR HOME_PAYROLL.VALUE=#p_payroll_code )
ORDER BY PER.LAST_NAME ASC,
PER.FIRST_NAME ASC,
PERSON_WKS.EFFECTIVE_DATE DESC
The Function in the 5th line is the one which is running slow. rest of the part is running in 4secs
The FUNCTION:
BEGIN
DECLARE
#v_ASGN_COUNT INT,
#v_RESULT INT
SELECT #v_ASGN_COUNT = COUNT(ASSIGNMENT_ID) --to find out if this employee has any assignment
FROM ASSIGNMENT
WHERE EXPATRIATE_PERSON_ID = #p_PERSON_ID AND
ASGN_STAT_CODE IN ('PD','A','I')
IF(#v_ASGN_COUNT > 0) --yes assignment, check against SECURITY_ASSIGNMENT_VW
BEGIN
SELECT #v_RESULT = COUNT(ASSIGNMENT_ID)
FROM SECURITY_ASSIGNMENT_VW
WHERE SEC_ACCOUNT_ID = #p_SEC_ACCOUNT_ID AND
ASSIGNMENT_ID IN (SELECT ASSIGNMENT_ID
FROM ASSIGNMENT
WHERE EXPATRIATE_PERSON_ID = #p_PERSON_ID AND
ASGN_STAT_CODE IN ('PD','A','I'))
END
ELSE --no assignment, so check against SECURITY_PERSON_VW
BEGIN
SELECT #v_RESULT = COUNT(PERSON_ID)
FROM SECURITY_PERSON_VW
WHERE SEC_ACCOUNT_ID = #p_SEC_ACCOUNT_ID AND
PERSON_ID = #p_PERSON_ID
END
RETURN #v_RESULT
END
Do the schemas match exactly... in particular check for missing indexes.
Well to begin with you have scalar functions which will run significantly slower as the number of records increase becasue they process row-by-agonizing-row. Not only that you've used the functions in joins which is a horrible practice if you need performance. You have a bunch of OR conditions which tend to slowness. And while it is too hard to actually read the code you posted (please try to format and only use all caps for keywords), I would suspect that some of those conditions are not sargable.
To know what is actually happening check the Execution plan (SQL Server) or Explain Plan (mySQL and others I think) or the equivalent feature in your database. Likely you wil find table scans which of course are going to get significantly slower as the number of records increases.
You may also have a problem with parameter sniffing. Please google to see how to fix that.
One improvement would be to make sure that dbo.FN_GETRPTSSIGNMENTID only gets executed once.
Currently, it gets executed three times.
You can replace two of those calls by joining to the field of the (one) remaing call.
Something like
SELECT WORKSHEET_ID
FROM PERSON PER
INNER JOIN PERSON EMPLEE ON EMPLEE.PERSON_ID = PER.PERSON_ID AND dbo.FN_CHECKRPTSECURITY(EMPLEE.PERSON_ID, #p_SEC_ACCOUNT_ID) > 0
INNER JOIN (
SELECT w1.ASSIGNMENT_ID
, w1.WORKSHEET_ID
, w1.EFFECTIVE_DATE
, w1.APPROVED_BY
, w3.CREATED_BY
FROM WORKSHEET_PAYROLL_VW w1
INNER JOIN WORKSHEET w3 ON w3.WORKSHEET_ID = w1.WORKSHEET_ID
WHERE w1.EFFECTIVE_DATE =
CASE WHEN #p_MOST_RECENT_ONLY = 'Y'
THEN (
SELECT MAX(w2.EFFECTIVE_DATE)
FROM WORKSHEET_PAYROLL_VW w2
WHERE w1.ASSIGNMENT_ID = w2.ASSIGNMENT_ID AND (ISNULL(#p_WKS_EFFECTIVE_DATE,w2.EFFECTIVE_DATE) = w2.EFFECTIVE_DATE)
)
ELSE ISNULL(#p_WKS_EFFECTIVE_DATE,w1.EFFECTIVE_DATE)
END
) PERSON_WKS ON PERSON_WKS.ASSIGNMENT_ID = dbo.FN_GETRPTASSIGNMENTID(EMPLEE.PERSON_ID)
INNER JOIN (
SELECT ASSIGNMENT_ID
, VALUE
FROM ASSIGNMENT_HISTORY AH
WHERE FIELD_NAME ='HOME PAYROLL GROUP'
AND EFFECTIVE_DATE = (
SELECT MAX(EFFECTIVE_DATE)
FROM ASSIGNMENT_HISTORY
WHERE ASSIGNMENT_ID = AH.ASSIGNMENT_ID
AND EFFECTIVE_DATE <=getDate()
AND FIELD_NAME = 'HOME PAYROLL GROUP'
)
LEFT JOIN SEARCH_ASSIGNMENT_VW PERSON_ASGN ON PERSON_ASGN.ASSIGNMENT_ID = PERSON_WKS.ASSIGNMENT_ID
LEFT JOIN LOOKUP EMPLEE_ASGN_STAT ON EMPLEE_ASGN_STAT.TYPE_ = 'ASSIGNMMENT_STATUS_CODE' AND EMPLEE_ASGN_STAT.CODE = PERSON_ASGN.ASGN_STAT_CODE
) HOME_PAYROLL ON HOME_PAYROLL.ASSIGNMENT_ID = PERSON_WKS.ASSIGNMENT_ID
WHERE (#p_SELECTED_PERSON_ONLY = 'N' OR EMPLEE.PERSON_ID = #p_PERSON_ID)
AND (#p_ASGN_STAT_CODE IS NULL OR PERSON_ASGN.ASGN_STAT_CODE = SUBSTRING(#p_ASGN_STAT_CODE,1,1) OR PERSON_ASGN.ASGN_STAT_CODE = SUBSTRING(#p_ASGN_STAT_CODE,2,1))
AND (#p_POLICY_ID IS NULL OR PERSON_ASGN.PROGRAM_CODE = #p_POLICY_ID)
AND (#p_HOME_COUNTRY_ID IS NULL OR PERSON_ASGN.HOMECOUNTRYID=#p_HOME_COUNTRY_ID)
AND (#p_HOME_CITY_ID IS NULL OR PERSON_ASGN.HOMECITYID=#p_HOME_CITY_ID )
AND (#p_HOME_COMPANY_ID IS NULL OR PERSON_ASGN.HOMEBUSINESSID=#p_HOME_COMPANY_ID )
AND (#p_HOME_DIVISION_ID IS NULL OR PERSON_ASGN.HOMECOMPONENTID=#p_HOME_DIVISION_ID )
AND (#p_HOST_COUNTRY_ID IS NULL OR PERSON_ASGN.HOSTCOUNTRYID=#p_HOST_COUNTRY_ID )
AND (#p_HOST_CITY_ID IS NULL OR PERSON_ASGN.HOSTCITYID=#p_HOST_CITY_ID )
AND (#p_HOST_COMPANY_ID IS NULL OR PERSON_ASGN.HOSTBUSINESSID=#p_HOST_COMPANY_ID )
AND (#p_HOST_DIVISION_ID IS NULL OR PERSON_ASGN.HOSTCOMPONENTID=#p_HOST_DIVISION_ID )
AND (#p_CREATED_BY IS NULL OR PERSON_WKS.CREATED_BY=#p_CREATED_BY )
AND (#p_APPROVED_BY IS NULL OR PERSON_WKS.APPROVED_BY=#p_APPROVED_BY )
AND (#p_payroll_code IS NULL OR HOME_PAYROLL.VALUE=#p_payroll_code )
ORDER BY
PER.LAST_NAME ASC
, PER.FIRST_NAME ASC
, PERSON_WKS.EFFECTIVE_DATE DESC