SQL Server 2014 if exists with multiple begin and end - sql

I have this line of codes:
if exists(select a.id, a.user_id
from AEmployeeLogs a
inner join AUsers b on b.id = a.user_id
where b.username = #username
and b.password = #password
and convert(date, a.date_in) = convert(date, dateadd(HOUR, 15, getdate())))
select 'Exist' as result;
else
begin
select
a.id, username, firstname, lastname, user_image, UserType, title,
'user_type_title', is_cashier,
case
when #num is null then 1
else #num + 1
end 'number'
from
dbo.AUsers a
inner join
ALookUp b on b.id = a.UserType
left join
AEmployeeLogs c on c.user_id = a.id
where
a.username = #username and a.password = #password
end
declare #id int;
select #id = a.id
from dbo.AUsers a
INNER JOIN ALookUp b
on b.id = a.UserType
where username = #username and password = #password
begin
INSERT INTO AEmployeeLogs (date_in,[user_id],note,isactive)
select dateadd(HOUR, 15, getdate()), #id, '',0
where #id is not null
end
The If Exists function works properly, but when I looked at the table AEmployeeLogs, it still inserts even though the is exists what is the proper way of writing my else statement when i have multiple begin and end functions in my query
NOTE: The first begin and end works it didn't select but the 2nd one works need help

Like already stated in the comments, the scope of the else has already ended after the first end.
Like following, it should work as expected:
IF EXISTS (
SELECT a.id,
a.user_id
FROM AEmployeeLogs a
INNER JOIN AUsers b ON b.id = a.user_id
WHERE b.username = #username
AND b.password = #password
AND CONVERT(DATE, a.date_in) = CONVERT(DATE, dateadd(HOUR, 15, getdate()))
)
SELECT 'Exist' AS result;
ELSE
BEGIN
SELECT a.id, username, firstname, lastname, user_image, UserType, title, 'user_type_title', is_cashier,
CASE
WHEN #num IS NULL
THEN 1
ELSE #num + 1
END 'number'
FROM dbo.AUsers a
INNER JOIN ALookUp b ON b.id = a.UserType
LEFT JOIN AEmployeeLogs c ON c.user_id = a.id
WHERE a.username = #username
AND a.password = #password
DECLARE #id INT;
SELECT #id = a.id
FROM dbo.AUsers a
INNER JOIN ALookUp b ON b.id = a.UserType
WHERE username = #username
AND password = #password
INSERT INTO AEmployeeLogs (
date_in,
[user_id],
note,
isactive
)
SELECT dateadd(HOUR, 15, getdate()),
#id,
'',
0
WHERE #id IS NOT NULL
END

Related

Updating table based on derived column as well as returning the resultset of the stored procedure

I have written a SQL Server stored procedure that returns a derived column in its result set. The derived column returns the difference in days and if the difference is less than 24 hours, then it returns hours.
I need to call an update statement based on value that comes from the derived column (NoOfDays) is -1: The storedprocedure would however return the entire resultset that includes the derived column and perform the update if necessary
update [org].[User]
set [Disabled] = 0
where id = #UserID AND ....
How do include this update statement to do that in this stored procedure
Stored procedure:
CREATE PROCEDURE declaration.UserAgreementsOutstanding
(#UserID INT)
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRY
UPDATE ua
SET ua.AcceptanceWindowExpiry = GETUTCDATE() + a.ReviewPeriodInDays
FROM declaration.UserAgreement ua
INNER JOIN declaration.Agreement a ON ua.AgreementID = a.ID
WHERE ua.USERID = #UserID
AND ua.AcceptanceWindowExpiry IS NULL;
SELECT
ua.ID AS UserAgreementID,
A.ID AS AgreementID,
A.Code,
A.ComplianceCode,
A.Name, A.Description,
A.Version,
ua.UserAgreementStateID,
uas.Name AS UserAgreementStateName,
ua.AcceptanceWindowExpiry,
declaration.GetDifferenceInDaysOrHours(ua.AcceptanceWindowExpiry) AS NoOfDays,
A.Data,
pa.ID AS AuthoredByID,
pa.FirstName + ' ' + pa.LastName AS AuthoredByName,
A.Authored,
ia.ID AS IssuedByID,
ia.FirstName + ' ' + pa.LastName AS IssuedByName,
A.Issued
FROM
declaration.Agreement AS A
INNER JOIN
declaration.UserAgreement AS ua ON A.ID = ua.AgreementID
INNER JOIN
declaration.UserAgreementState AS uas ON ua.UserAgreementStateID = uas.ID
LEFT JOIN
common.Person AS pa ON A.AuthoredBy = pa.ID
LEFT JOIN
common.Person AS ia ON A.IssuedBy = ia.ID
WHERE
ua.UserID = 607
AND uas.Code IN ('ISS', 'DEF') -- Issued, Deferred
AND A.Draft = CONVERT(BIT, 0) -- Not a draft.
AND A.Deleted = CONVERT(BIT, 0) -- Not deleted.
AND (A.Issued <= GETUTCDATE() OR A.Issued IS NULL)
AND (A.Expires > GETUTCDATE() OR A.Expires IS NULL)
END TRY
BEGIN CATCH
-- do some pseudo logging
PRINT ERROR_MESSAGE();
THROW;
END CATCH;
END;
Function
CREATE FUNCTION declaration.GetDifferenceInDaysOrHours(#AcceptanceWindowExpiry datetime)
RETURNS int
AS
BEGIN
DECLARE #timeDifferenceInDays INT;
DECLARE #timeDifferenceInHours INT;
DECLARE #timeDifference INT;
SELECT #timeDifferenceInDays = DATEDIFF(d, GETUTCDATE(), #AcceptanceWindowExpiry)
IF #timeDifferenceInDays > 1
BEGIN
SELECT #timeDifference = #timeDifferenceInDays
END
ELSE
BEGIN
SELECT #timeDifferenceInHours = DATEDIFF(HOUR, GETUTCDATE(), #AcceptanceWindowExpiry)
IF #timeDifferenceInHours >= 0 AND #timeDifferenceInHours <= 24
BEGIN
SELECT #timeDifference = #timeDifferenceInHours
END
ELSE
BEGIN
SELECT #timeDifference = -1
END
END
RETURN #timeDifference;
END;
The current resultset
You can add UPDATE statement to disable the user before updating the user agreement. Also, have the transaction scope.
BEGIN TRY
BEGIN TRANSACTION;
DECLARE #OutStandingUserAgreements TABLE(UserID INT, AgreementID INT, TimeDifference INT)
INSERT INTO #OutStandingUserAgreements(UserID, AgreementID , TimeDifference)
SELECT U.Id
, UA.AgreementID
, declaration.UserAgreementsOutstanding(UA.AcceptanceWindowExpiry) AS TimeDifference
FROM [org].[User] AS U
INNER JOIN declaration.UserAgreement AS UA
ON U.UserID = UA.UserID
where U.id = #UserID;
-- We are disabling user here, based on the UserAgreement Status
UPDATE U
SET U.[Disabled] = 0
FROM [org].[User] AS U
WHERE EXISTS (SELECT 1 FROM
#OutStandingUserAgreements AS oua
WHERE oua.UserID = U.ID
AND oua.TimeDifference = -1);
UPDATE ua
SET ua.AcceptanceWindowExpiry = GETUTCDATE() + a.ReviewPeriodInDays
FROM declaration.UserAgreement ua
INNER JOIN declaration.Agreement a ON ua.AgreementID = a.ID
WHERE ua.USERID = #UserID
AND ua.AcceptanceWindowExpiry IS NULL;
IF EXISTS(SELECT 1 FROM Org.User WHERE Id = #UserID AND Disabled = 0)
BEGIN
SELECT -1;
END
ELSE
BEGIN
SELECT
ua.ID AS UserAgreementID,
A.ID AS AgreementID,
A.Code,
A.ComplianceCode,
A.Name, A.Description,
A.Version,
ua.UserAgreementStateID,
uas.Name AS UserAgreementStateName,
ua.AcceptanceWindowExpiry,
oua.TimeDifference AS NoOfDays,
A.Data,
pa.ID AS AuthoredByID,
pa.FirstName + ' ' + pa.LastName AS AuthoredByName,
A.Authored,
ia.ID AS IssuedByID,
ia.FirstName + ' ' + pa.LastName AS IssuedByName,
A.Issued
FROM
declaration.Agreement AS A
INNER JOIN
declaration.UserAgreement AS ua ON A.ID = ua.AgreementID
INNER JOIN
declaration.UserAgreementState AS uas ON ua.UserAgreementStateID = uas.ID
INNER JOIN #OutStandingUserAgreements AS oua
ON oua.AgreementID = ua.AgreementID
LEFT JOIN
common.Person AS pa ON A.AuthoredBy = pa.ID
LEFT JOIN
common.Person AS ia ON A.IssuedBy = ia.ID
WHERE
ua.UserID = 607
AND uas.Code IN ('ISS', 'DEF') -- Issued, Deferred
AND A.Draft = CONVERT(BIT, 0) -- Not a draft.
AND A.Deleted = CONVERT(BIT, 0) -- Not deleted.
AND (A.Issued <= GETUTCDATE() OR A.Issued IS NULL)
AND (A.Expires > GETUTCDATE() OR A.Expires IS NULL)
END
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION;
END CATCH

Returning column with count of 0

I have a query that looks up a list of documents depending on their department and their status.
DECLARE #StatusIds NVARCHAR(MAX) = '1,2,3,4,5';
DECLARE #DepartmentId NVARCHAR(2) = 'IT';
SELECT ILDPST.name,
COUNT(*) AS TodayCount
FROM dbo.TableA ILDP
LEFT JOIN dbo.TableB ILDPS ON ILDPS.IntranetLoanDealPreStateId = ILDP.IntranetLoanDealPreStateId
LEFT JOIN dbo.TableC ILDPST ON ILDPST.IntranetLoanDealPreStateTypeId = ILDPS.CurrentStateTypeId
WHERE (ILDP.CreatedByDepartmentId = #DepartmentId OR #DepartmentId IS NULL)
AND ILDPS.CurrentStateTypeId IN (
SELECT value
FROM dbo.StringAsIntTable(#StatusIds)
)
GROUP BY ILDPST.name;
This returns the results:
However, I'd also like to be able to return statuses where the TodayCount is equal to 0 (i.e. any status with an id included in #StatusIds should be returned, regardless of TodayCount).
I've tried messing with some unions / joins / ctes but I couldn't quite get it to work. I'm not much of an SQL person so not sure what else to provide that could be useful.
Thanks!
If you want to have all the records from TableC you need to left join all other tables to it, not left join it to the other tables. Also it's best to INNER JOIN the filtering table you create from #StatusIds rather then apply it through INclause. Try this:
DECLARE #StatusIds NVARCHAR(MAX) = '1,2,3,4,5';
DECLARE #DepartmentId NVARCHAR(2) = 'IT';
SELECT ILDPST.Name, COUNT(ILDP.IntranetLoanDealPreStateId) AS TodayCount
FROM (SELECT DISTINCT value FROM dbo.StringAsIntTable(#StatusIds)) StatusIds
INNER JOIN dbo.TableC ILDPST
ON ILDPST.IntranetLoanDealPreStateTypeId = StatusIds.value
LEFT JOIN dbo.TableB ILDPS
ON ILDPS.CurrentStateTypeId = ILDPST.IntranetLoanDealPreStateTypeId
LEFT JOIN dbo.TableA ILDP
ON ILDP.IntranetLoanDealPreStateId = ILDPS.IntranetLoanDealPreStateId
AND (ILDP.CreatedByDepartmentId = #DepartmentId OR #DepartmentId IS NULL)
GROUP BY ILDPST.Name;
Try this instead:
DECLARE #StatusIds NVARCHAR(MAX) = '1,2,3,4,5';
DECLARE #DepartmentId NVARCHAR(2) = 'IT';
SELECT ILDPST.name,
COUNT(ILDP.IntranetLoanDealPreStateId) AS TodayCount
FROM
dbo.TableC ILDPST
LEFT JOIN
dbo.TableB ILDPS ON ILDPST.IntranetLoanDealPreStateTypeId = ILDPS.CurrentStateTypeId
LEFT JOIN
dbo.TableA ILDP ON ILDPS.IntranetLoanDealPreStateId = ILDP.IntranetLoanDealPreStateId
AND (ILDP.CreatedByDepartmentId = #DepartmentId OR #DepartmentId IS NULL)
WHERE
ILDPST.IntranetLoanDealPreStateTypeId
IN (
SELECT value
FROM dbo.StringAsIntTable(#StatusIds)
)
GROUP BY ILDPST.name;
You could use the following function to create a table value for your status id's.
CREATE FUNCTION [dbo].[SplitString]
(
#myString varchar(max),
#deliminator varchar(2)
)
RETURNS
#ReturnTable TABLE
(
[Part] [varchar](max) NULL
)
AS
BEGIN
Declare #iSpaces int
Declare #part varchar(max)
--initialize spaces
Select #iSpaces = charindex(#deliminator,#myString,0)
While #iSpaces > 0
Begin
Select #part = substring(#myString,0,charindex(#deliminator,#myString,0))
Insert Into #ReturnTable(Part)
Select #part
Select #myString = substring(#mystring,charindex(#deliminator,#myString,0)+ len(#deliminator),len(#myString) - charindex(' ',#myString,0))
Select #iSpaces = charindex(#deliminator,#myString,0)
end
If len(#myString) > 0
Insert Into #ReturnTable
Select #myString
RETURN
END
This can now be used as a table that you can LEFT JOIN to.
DECLARE #StatusIds NVARCHAR(MAX) = '1,2,3,4,5';
SELECT * FROM dbo.SplitString(#StatusIds, ',')
It is not tested but give it a try:
;With Cte ( Value ) As
( Select Distinct Value From dbo.StringAsIntTable( #StatusIds ) )
Select
ILDPST.name,
COUNT(*) AS TodayCount
From
dbo.TableC As ILDPST
Inner Join Cte On ( ILDPST.IntranetLoanDealPreStateTypeId = Cte.Value )
Left Join dbo.TableB As ILDPS On ( ILDPST.IntranetLoanDealPreStateTypeId = ILDPS.CurrentStateTypeId )
Left Join dbo.TableA As ILDP On ( ILDPS.IntranetLoanDealPreStateId = ILDP.IntranetLoanDealPreStateId )
And ( ( ILDP.CreatedByDepartmentId = #DepartmentId ) Or ( #DepartmentId Is Null ) )
Group By
ILDPST.name

error in IF ELSE statement in SQL [duplicate]

This question already has an answer here:
Drop temp table within IF ELSE statement
(1 answer)
Closed 7 years ago.
I have the following stored procedure, But seems like the #Temp table is creating troubles in it. I get following error
There is already an object named '#Temp' in the database.
I guess somethings wrong with my IF ELSE
Here is the stored procedure:
create procedure spGetHOSalesReport
#DateFrom datetime,#DateTo datetime,#EmbossLine varchar(20),#CountryID int,#status char(2)
AS
Set #DateTo = #DateTo +1
if(#status = 'E1')
begin
Select PT.[ID] 'TransactionID', PT.BatchNumber, PT.SequenceNumber, PT.TransactionDate,
PT.TerminalID, PT.TotalAmount, PT.TransactionTypeID, TT.TransactionType,PT.PAN 'EmbossLine',PT.PreBalanceAmount, PT.PostBalanceAmount, RefTxnID, SettlementDate,PaidCash, CreditAmount, DiscountAmount,
RefPAN, PT.Remarks, ' ' + CashierCard as 'SupervisorCard',St.StoreID
into #Temp
from TempPOS_Transactions PT inner join TransactionType TT on TT.TransactionTypeID = PT.TransactionTypeID
inner join Staff St on St.CardNumber=PT.CashierCard
where
PT.[ID] not in (Select distinct isnull(TransactionID,0) from Testcards)
and (PT.TransactionDate >= #DateFrom) and (PT.TransactionDate < #DateTo)
and (PT.TransactionTypeID = 6) and (PT.BatchNumber = 0) and (Pt.SequenceNumber =-1)
select T.*, ' '+ C.EmbossLine+' ' as 'EmbossLine', C.EmbossLine as 'EmbossLine1',
isnull(C.FirstName,'') +' '+ isnull(C.LastName,'') 'EmbossName',C.FirstName,C.LastName,City.CityName,Country.CountryName,Country.CurrencyName, PM.MerchantID, PM.MerchantName1, C.AccountNumber, C.VehicleNumber, C.ExpiryDate ,
case C.Status when 'E0' then 'Authorized' when 'E1' then 'Pending' end 'Status'
from #Temp T
inner join Card C on C.EmbossLine= T.EmbossLine
inner join Terminal on Terminal.TerminalID = T.TerminalID
inner join Merchant PM on PM.MerchantID = Terminal.MerchantID
inner join City on City.CityID = PM.CityID
inner join Country on Country.CountryID = PM.CountryID
where C.Status <>'E3'
and C.CardID not in (Select distinct isnull(CardID,0) from Testcards)
and (C.EmbossLine like '%'+#EmbossLine+'%' or #EmbossLine like '-999')
and (PM.CountryID = #CountryID or #CountryID ='-999')
and (C.Status = #status)
order by T.TransactionDate, MerchantName1, T.BatchNumber, T.SequenceNumber
End
Else
Begin
Select PT.[ID] 'TransactionID', PT.BatchNumber, PT.SequenceNumber, PT.TransactionDate,
PT.TerminalID, PT.TotalAmount, PT.TransactionTypeID, TT.TransactionType,PT.PAN 'EmbossLine',PT.PreBalanceAmount, PT.PostBalanceAmount, RefTxnID, SettlementDate,PaidCash, CreditAmount, DiscountAmount,
RefPAN, PT.Remarks, ' ' + CashierCard as 'SupervisorCard',St.StoreID
into #Temp
from POS_Transactions PT inner join TransactionType TT on TT.TransactionTypeID = PT.TransactionTypeID
inner join Staff St on St.CardNumber=PT.CashierCard
where PT.[ID] not in (Select distinct isnull(TransactionID,0) from Testcards) and (PT.TransactionDate >= #DateFrom) and (PT.TransactionDate < #DateTo)
and (PT.TransactionTypeID = 6) and (PT.BatchNumber = 0) and (Pt.SequenceNumber =-1)
select T.*, ' '+ C.EmbossLine+' ' as 'EmbossLine', C.EmbossLine as 'EmbossLine1',
isnull(C.FirstName,'') +' '+ isnull(C.LastName,'') 'EmbossName',C.FirstName,C.LastName,City.CityName,Country.CountryName,Country.CurrencyName, PM.MerchantID, PM.MerchantName1, C.AccountNumber, C.VehicleNumber, C.ExpiryDate ,
case C.Status when 'E0' then 'Authorized' when 'E1' then 'Pending' end 'Status'
from #Temp T
inner join Card C on C.EmbossLine= T.EmbossLine
inner join Terminal on Terminal.TerminalID = T.TerminalID
inner join Merchant PM on PM.MerchantID = Terminal.MerchantID
inner join City on City.CityID = PM.CityID
inner join Country on Country.CountryID = PM.CountryID
where C.Status <>'E3'
and C.CardID not in (Select distinct isnull(CardID,0) from Testcards)
and (C.EmbossLine like '%'+#EmbossLine+'%' or #EmbossLine like '-999')
and (PM.CountryID = #CountryID or #CountryID ='-999')
and (C.Status = #status)
order by T.TransactionDate, MerchantName1, T.BatchNumber, T.SequenceNumber
End
drop table #Temp
You cannot have two statements in the same procedure that creates a temp table with the same name. This is a leftover from SQL 6.5 which did not have deferred name resolution.
And in any case, it only makes sense if the tables are created exactly the same, else your procedure will behave very funky.
So instead of using SELECT INTO, use CREATE TABLE + INSERT.
UPDATE
According to the selected way from comment:
Second option: First create temp table and insert
First let's create the temp table. For that you should modify your procedure like:
create procedure spGetHOSalesReport
#DateFrom datetime,#DateTo datetime,#EmbossLine varchar(20),#CountryID int,#status char(2)
AS
BEGIN -- begin procedure
SET #DateTo = #DateTo +1
if object_id('tempdb..#Temp') is not null drop table #Temp
create table #Temp
( TransactionID int
, BatchNumber ... ( your type of field )
, SequenceNumber ...
, TransactionDate ...
, TerminalID int
, TotalAmount ...
, TransactionTypeID int
, TransactionType ...
, EmbossLine ...
, PreBalanceAmount ...
, PostBalanceAmount ...
, RefTxnID int
, SettlementDate ...
, PaidCash ...
, CreditAmount ...
, DiscountAmount ...
, RefPAN ...
, Remarks ...
, SupervisorCard ...
, StoreID int
)
if(#status = 'E1')
.......
I do not know which data type has these fields, so, you have to do yourself. Then edit insert into temp table in first case and similar in another case:
insert into #Temp
Select PT.[ID] 'TransactionID', PT.BatchNumber, PT.SequenceNumber, PT.TransactionDate,
PT.TerminalID, PT.TotalAmount, PT.TransactionTypeID, TT.TransactionType,PT.PAN 'EmbossLine',PT.PreBalanceAmount, PT.PostBalanceAmount, RefTxnID, SettlementDate,PaidCash, CreditAmount, DiscountAmount,
RefPAN, PT.Remarks, ' ' + CashierCard as 'SupervisorCard',St.StoreID
from TempPOS_Transactions PT inner join TransactionType TT on TT.TransactionTypeID = PT.TransactionTypeID
inner join Staff St on St.CardNumber=PT.CashierCard
where ...
In the end of procedure you can add:
End -- end of your if
if object_id('tempdb..#Temp') is not null drop table #Temp
END -- end of procedure
But the simplest way is create two different temp tables:
if(#status = 'E1')
begin
if object_id('tempdb..#Temp1') is not null drop table #Temp1
Select PT.[ID] 'TransactionID', PT.BatchNumber, ...
into #Temp1
from TempPOS_Transactions PT
inner join TransactionType TT on TT.TransactionTypeID = PT.TransactionTypeID
.....
end
else
begin
if object_id('tempdb..#Temp2') is not null drop table #Temp2
Select PT.[ID] 'TransactionID', PT.BatchNumber, ...
into #Temp2
from POS_Transactions PT
inner join TransactionType TT on TT.TransactionTypeID = PT.TransactionTypeID
....
end
Also, you can write just two select without creating temp table in this case

Querying Different Table If First Result is Empty

I'm writing a stored procedure to look in two tables PersonTbl, UserTbl. First search the PersonTbl for an userID and if the userID is there get an email address from the UserTbl and return both. However if the ID is not there then search two other tables (PersonsPendingTbl, UsersPendingTbl) for the ID and email. If the ID is not found once again, return null/nulls. So far this is what I've come up with, but not sure if it's the best way of writing it. Let me know if there's any changes you would recommend;
create PROCEDURE [dbo].[MyNewSP]
#ID VARCHAR(MAX)
AS
DECLARE #userID VARCHAR(50)
DECLARE #Email VARCHAR(100)
DECLARE #currentlyActive CHAR
BEGIN
SELECT
#userID = userTbl.ID ,
#Email = personTbl.EMAIL,
#currentlyActive = 'Y'
FROM
personTbl
INNER JOIN userTbl ON personTbl.person_id = userTbl.person_id
WHERE
( userTbl.ID = #ID )
IF ( #userID != #ID ) --Check to see if null
BEGIN
SELECT #currentlyActive = 'N'
SELECT
upt.ID ,
ppt.EMAIL,
#currentlyActive
FROM
PersonsPendingTbl ppt
INNER JOIN dbo.UsersPendingTbl upt ON ppt.person_id = upt.person_id
WHERE
( upt.ID = #ID )
END
ELSE
BEGIN
SELECT
#userID ,
#Email ,
#currentlyActive
END
END
Make a union of both results, but always pick the first row. If the user is registered as Active AND Inactive, it'll return the Active one:
Select *
from (
SELECT userTbl.ID AS UID, personTbl.EMAIL as email, 'Y' as active
FROM personTbl
JOIN userTbl ON personTbl.person_id = userTbl.person_id
WHERE (userTbl.ID = #ID)
union all
SELECT upt.ID AS UID, ppt.EMAIL as email, 'N' as active
FROM PersonsPendingTbl ppt
INNER JOIN dbo.UsersPendingTbl upt ON ppt.person_id = upt.person_id
WHERE (upt.ID = #ID)) user
limit 0,1
I'm not sure about uniqueness of values between your pending and non-pending table, but this should be close enough to get you going.
select
case
when p.PersonId is null and pp.personPendingId is null then null
else userid
end as userid,
case
when p.PersonId is not null then p.email
when p.PersonId is null and pp.PersonPendingID is not null then pp.email
else null
end as email,
case
when p.PersonId is not null then 'Y'
when p.PersonId is null and pp.PersonPendingID is not null then 'N'
else null
end as CurrentlyActive
from userTbl u
left join PersonTbl p on u.Person_id = p.PersonId
left join userPendingTbl up on u.UserId = up.UserPendingId
left join PersonPendingTbl pp on up.personPendingId = pp.PersonPendingID
where u.UserId = #ID

SQL Server trigger on a field that's updated

I have the following trigger:
BEGIN
DECLARE #email varchar(200)
DECLARE #jobcode int
DECLARE #status char(1)
DECLARE #emaild varchar(200)
DECLARE #jobcoded int
DECLARE #statusd char(1)
SET #statusd = NULL
SELECT #status = z.status, #email = p.EMail, #jobcode = z.jobID
FROM zipoutfiles z
INNER JOIN inserted AS i ON z.jobID = i.jobID
INNER JOIN PS_LoginUser AS p ON z.UserID = p.UserID
SELECT #statusd = z.status, #emaild = p.EMail, #jobcoded = z.jobID
FROM zipoutfiles z
INNER JOIN deleted AS d ON z.jobID = d.jobID
INNER JOIN PS_LoginUser AS p ON z.UserID = p.UserID
WHERE d.jobID = #jobcode
IF ((#status = 'D' AND #statusd = 'R') OR (#status = 'D' AND #statusd = 'E'))
BEGIN
EXEC SendMail #email, #jobcode
END
END
I want to be able to run SendMail when status goes from E to D or R to D, but not D to D (if it gets updated again) and also when it gets inserted as D. What am I doing wrong here:
Not sure what your table schemas are, but this may get you all of the appropriate emails:
select p.EMail as Email, z.JobId as JobCode
from ZipOutFiles as ZOF inner join
inserted as i on i.JobId = ZOF.JobId inner join
PS_LoginUser as PLU on PLU.UserId = ZOF.UserId left outer join
deleted as d on d.JobId = ZOF.JobId
where
( d.Status = 'E' and i.Status = 'D' ) or -- E -> D.
( d.Status = 'R' and i.Status = 'D' ) or -- R -> D.
( d.Status is NULL and i.Status = 'D' ) -- Inserted D.
I've assumed that you aren't really updating JobId. If so, how do you match the before and after rows?
Also assumed is that Status cannot be NULL. If so, the last condition needs to be modified to properly detect no corresponding row was found in the deleted table.