Querying Different Table If First Result is Empty - sql

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

Related

how to make inner join query for getting multiple tables selected column

i just working out project school management. now i just made query for retrieve other table columns. here is my query :
ALTER PROCEDURE [dbo].[GetTeacherList]
(
#teacherid varchar(5) = null,
#classid varchar(5) = null,
#sectionid varchar(5) = null,
#subjectid varchar(5) = null
)
AS
BEGIN
SET NOCOUNT ON;
select *,right('00000' + CAST(t.[PK_PID] AS varchar(5)) ,5) as ID, c.ClassName, su.SubjectName, s.SectionName
from teachers t
inner join teacherclassassign tc on t.PK_PID = tc.TeacherID or (t.PK_PID is null and tc.TeacherID is null )
inner join classes c on c.PK_PID = tc.ClassID or (c.PK_PID is not null and tc.ClassID is null)
inner join sections s on s.PK_PID = tc.SectionID or (s.PK_PID is not null and tc.SectionID is null)
inner join subjects su on su.PK_PID = tc.SubjectID or (su.PK_PID is not null and tc.SubjectID is null)
where 1=1
and (#teacherid is null or tc.[TeacherID] = CONVERT(INT,#teacherid))
and (#classid is null or tc.[ClassID] = CONVERT(INT,#classid))
and (#sectionid is null or tc.[SectionID] = CONVERT(INT,#sectionid))
and (#subjectid is null or tc.[SubjectID] = CONVERT(INT,#subjectid))
order by t.PK_PID asc
END
how ever it's return me two rows how ever i want all rows from table teachers.
here is rows data i want :
and here is all data of teachers :
how i achieve this result..please guys help me.
You need to replace the first inner join with the LEFT Join as you want all teachers.
Below i have changed the query,See if this fixes the problem
SET NOCOUNT ON;
select *,right('00000' + CAST(t.[PK_PID] AS varchar(5)) ,5) as ID, c.ClassName, su.SubjectName, s.SectionName
from teachers t
LEFT join teacherclassassign tc on t.PK_PID = tc.TeacherID or (t.PK_PID is null and tc.TeacherID is null )
inner join classes c on c.PK_PID = tc.ClassID or (c.PK_PID is not null and tc.ClassID is null)
inner join sections s on s.PK_PID = tc.SectionID or (s.PK_PID is not null and tc.SectionID is null)
inner join subjects su on su.PK_PID = tc.SubjectID or (su.PK_PID is not null and tc.SubjectID is null)
where 1=1
and (#teacherid is null or tc.[TeacherID] = CONVERT(INT,#teacherid))
and (#classid is null or tc.[ClassID] = CONVERT(INT,#classid))
and (#sectionid is null or tc.[SectionID] = CONVERT(INT,#sectionid))
and (#subjectid is null or tc.[SubjectID] = CONVERT(INT,#subjectid))
order by t.PK_PID asc
END

SQL Server 2014 if exists with multiple begin and end

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

Adding parameters to where clause sql

I am something of a beginner to SQL and I am trying to run the following SP.
DECLARE #stringStatus varchar(100)
--Check for status value
IF #Status is NULL
BEGIN
set #stringStatus = ''
END
ELSE
BEGIN
set #stringStatus = ' and ps.Status = ' + CAST(#Status as varchar)
END
select * from Projects p
join projectstatus ps on p.pid = ps.pid
where ps.Category = isnull(#Category, p.Category) + #stringStatus
The aim of the above is to get all rows if #Status is NULL, and to filter the rows, if a parameter has been assigned to #Status.
#Category (varchar) and #Status (int) are IN paramateres
This works fine when #Status is NULL, i.e, I get all the records. But if I pass a parameter, say, #Status = 2, the execution returns no rows, even though there are a few records available.
First of all, how do I get my desired results? Secondly, is there a better way to do this without an if condition block?
Actually, your result is
select * from something where ps.Category ='some string, containing and ps.Status= inside'
So empty rowset is expected result.
You want something like this (hope status is number, not string)
select * from Projects p
join projectstatus ps on p.pid = ps.pid
where ps.Category = isnull(#Category, p.Category) and
(#Status is NULL OR ps.Status = #Status)
Ok, here are tests for mistrustful :-)
declare #projects table
(
pid int,
name nvarchar(20),
category int
);
declare #projectstatus table
(
pid int,
Category int,
status int
);
insert into #projects values
(1,'Project 1', 1),(2,'Project 2',1),(3,'Project 3',1),(4,'Project 4',1),(5,'Project 5',1);
insert into #projectstatus values
(1,1,1),(2,1,2),(3,1,3),(4,1,2),(5,1,NULL);
declare #Category int =null;
declare #Status int;
--first of all, do not understand, what is the logic with category
--category in one table should be the same, than in other table or specified?
--ok, you said with category everything is ok, do not test category, test status
--test with null
set #Status=null
select * from #Projects p
join #projectstatus ps on p.pid = ps.pid
where ps.Category = isnull(#Category, p.Category) and
(#Status is NULL OR ps.Status = #Status)
--test with existing status
set #Status=1
select * from #Projects p
join #projectstatus ps on p.pid = ps.pid
where ps.Category = isnull(#Category, p.Category) and
(#Status is NULL OR ps.Status = #Status)
--test with not existing status
set #Status=10
select * from #Projects p
join #projectstatus ps on p.pid = ps.pid
where ps.Category = isnull(#Category, p.Category) and
(#Status is NULL OR ps.Status = #Status)
You can simple put condition in the below way for your desired results
--Check for status value
IF #Status is NULL
BEGIN
select * from Projects p
join projectstatus ps on p.pid = ps.pid
where ps.Category = isnull(#Category, p.Category)
END
ELSE
BEGIN
select * from Projects p
join projectstatus ps on p.pid = ps.pid
where ps.Category = isnull(#Category, p.Category) + #stringStatus
END
Thanks

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.

SP executing error

I am writing below SP.But when i try to run this query i am getting this error:
There is already an object named
'#myCourses1' in the database.
So this getting in two else loops. also
create proc [dbo].[GetOrdersByUserIDwithSubscription]
(
#UserID int
)
as
begin
declare #status varchar(500)
declare #substatus char(2)
select #substatus=Subscribe_status from tbl_user where userid=#userid
print #substatus
if #substatus='N'
BEGIN
select a.*, b.CategoryText, Cast('' as Varchar(10)) as SectionsViewed, PurchasedDate as dateadded into #myCourses1 from dbo.Tbl_CourseInformations a JOIN Tbl_Categories b ON a.AssignCategory = b.CategoryID
Join Tbl_Orders c ON c.UserID = #UserID and c.CourseID = a.CourseID and c.courseprice<>'subscriber'
Order By CategoryText, CourseTitle
END
else if #substatus=''
BEGIN
select a.*, b.CategoryText, Cast('' as Varchar(10)) as SectionsViewed, PurchasedDate as dateadded into #myCourses1 from dbo.Tbl_CourseInformations a JOIN Tbl_Categories b ON a.AssignCategory = b.CategoryID
Join Tbl_Orders c ON c.UserID = #UserID and c.CourseID = a.CourseID and c.courseprice<>'subscriber'
Order By CategoryText, CourseTitle
END
else if #substatus='Y'
BEGIN
select a.*, b.CategoryText, Cast('' as Varchar(10)) as SectionsViewed, PurchasedDate as dateadded into #myCourses1 from dbo.Tbl_CourseInformations a JOIN Tbl_Categories b ON a.AssignCategory = b.CategoryID
Join Tbl_Orders c ON c.UserID = #UserID and c.CourseID = a.CourseID
Order By CategoryText, CourseTitle
END
The SQL Parser is choking because you have used the same temp table name in different parts of the IF statement. The IF does not have scope like other programming languages.
If you do not need to reference the temp table outside of each of the IF blocks you can get around the problem by using a different table name in each part.
Have a look at my answer to a similar question.
Also, the monstrocity of a query you have could be reduced to this:
create proc [dbo].[GetOrdersByUserIDwithSubscription](
#UserID int
)
as
begin
declare #substatus char(2)
select #substatus = Subscribe_status
from tbl_user
where userid = #userid
select a.*, b.CategoryText,
Cast("" as Varchar(10)) as SectionsViewed,
PurchasedDate as dateadded
from dbo.Tbl_CourseInformations a
join Tbl_Categories b ON a.AssignCategory = b.CategoryID
join Tbl_Orders c ON c.UserID = #UserID
and c.CourseID = a.CourseID
and (#substatus = 'N' or c.courseprice <> 'subscriber')
order by CategoryText, CourseTitle
END
Explicitly create the temp table at the beginning of the proc.
CREATE TABLE #myCourses1 (
...
)
Then write your SELECT statements as:
INSERT INTO #myCourses1
select a.*, b.CategoryText, Cast('' as Varchar(10)) as SectionsViewed, PurchasedDate as dateadded
from dbo.Tbl_CourseInformations
...
You syntax is
SELECT [Column-List] INTO #TempTable FROM [Rest-of-Query]
When using this syntax, Sql Server attempts to create #TempTable on the fly based on your column list (source).
To get around this, either Drop #TempTable at the beginning of the stored procedure (if you do not need its data beyond the scope of the SP), or make it a permanent table.