How to write SQL query inside else statement in SQL Server - sql-server

I want to find if query does not return any results, then print 'no records found' else execute the query.
Here is my query,
select case when exists (
SELECT CAST(dm.[ID] AS VARCHAR(100)) as ID, case when dm.[Que_Type] = 0 then 'Valid' else 'Invalid' end [Type],
dm.[Name_List], t.[Name], dm.[FromDate], dm.[ToDate] FROM tblDays dm(nolock)
inner join (select pr.ID, pr.name from tblProduct pr(nolock)) as t
on dm.TradeID = t.ID where 1=1 and dm.ToDate between GETDATE() and DATEADD(dd, 15, GETDATE()))
then 'ok'
else 'no records'
end
In this query, I want to execute the query instead of printing 'ok'. How can I do that?

You could use an if statement along with exists
Since the conditional check is just to see if any records are returned, there is no need to select all those columns, so we just select 1. If records are found, the if tests true, and we'll run the sql statement. If no records are found, we'll drop to the else block and print 'no records'.
This may work for you:
IF(
exists(
select 1
FROM tblDays dm(nolock)
inner join (select pr.ID, pr.name from tblProduct pr(nolock)) as t
on dm.TradeID = t.ID
where 1=1
and dm.ToDate between GETDATE() and DATEADD(dd, 15, GETDATE())
)
)
BEGIN
SELECT CAST(dm.[ID] AS VARCHAR(100)) as ID
, case when dm.[Que_Type] = 0 then 'Valid' else 'Invalid' end [Type]
, dm.[Name_List]
, t.[Name]
, dm.[FromDate]
, dm.[ToDate]
FROM tblDays dm(nolock)
inner join (select pr.ID, pr.name from tblProduct pr(nolock)) as t
on dm.TradeID = t.ID
where 1=1
and dm.ToDate between GETDATE() and DATEADD(dd, 15, GETDATE())
END
ELSE
BEGIN
print 'no records'
END

You could use ##ROWCOUNT:
According to BOL:
Returns the number of rows affected by the last statement.
SELECT
CAST(dm.[ID] AS VARCHAR(100)) AS ID,
CASE WHEN dm.[Que_Type] = 0 THEN 'Valid' ELSE 'Invalid' END AS [Type],
dm.[Name_List],
t.[Name],
dm.[FromDate],
dm.[ToDate]
FROM tblDays dm(NOLOCK)
INNER JOIN (
SELECT
pr.ID,
pr.name
FROM tblProduct pr(NOLOCK)
) AS t
ON dm.TradeID = t.ID
WHERE
1 = 1
AND dm.ToDate BETWEEN GETDATE() AND DATEADD(dd, 15, GETDATE())
IF ##ROWCOUNT = 0
PRINT 'No records found.'

Related

SQL Server if condition based on date

I need help with, giving the if exists and if not exists condition.
I want to write an if condition, based on date, such that, if any row exists in table1 on current date TARGET_DT for a particular job, then do some action
else do other action.
IF EXISTS(SELECT 1 FROM COD_BLU_OPENING_VOLUME
WHERE TARGET_DT = CONVERT(DATETIME, GETDATE(), 101) AND JOBID = #OPENJOB)
BEGIN
IF(SELECT COUNT(1) FROM COD_BLU_INVENTORY WITH(NOLOCK)
WHERE (JOBID = #JOB AND STATUS = 'A' AND TARGETDT = CONVERT(DATETIME, #TARGETDT, 101))) = 0
BEGIN
INSERT INTO COD_BLU_INVENTORY(JOBID, TARGETDT, CARRYOVER, FRESHVOL, TOTALVOL, STATUS, UPDATEDBY, UPDATEDT, OPENINGVOL)
VALUES(#JOB, #TARGETDT, #CARRYOVERVOL, #FRESHVOL, #TOTALVOL, 'A', #EMPCODE, GETDATE(), #CARRYOVERVOL)
SELECT '1'
END
ELSE
BEGIN
SELECT'0'
END
END
ELSE IF NOT EXISTS(SELECT 1 FROM COD_BLU_OPENING_VOLUME
WHERE TARGET_DT = CONVERT(DATETIME, GETDATE(), 101)
AND TARGET_DT < CONVERT(DATETIME, GETDATE(), 101)
AND JOBID = #OPENJOB)
BEGIN
INSERT INTO COD_BLU_OPENING_VOLUME(TARGET_DT, JOBID, OPENING_COUNT, UPDATED_BY, UPDATED_DT, PRE_ASSIGNEDCOUNT)
VALUES(#OPENTARDT, #OPENJOB, #OPENCNT, #OPENEMPCODE, GETDATE(), #PREOPENCNT)
IF (SELECT COUNT(1) FROM COD_BLU_INVENTORY WITH(NOLOCK)
WHERE (JOBID = #JOB AND STATUS = 'A'
AND TARGETDT = CONVERT(DATETIME, #TARGETDT, 101))) = 0
BEGIN
INSERT INTO COD_BLU_INVENTORY(JOBID, TARGETDT, CARRYOVER, FRESHVOL, TOTALVOL, STATUS, UPDATEDBY, UPDATEDT, OPENINGVOL)
VALUES(#JOB, #TARGETDT, #CARRYOVERVOL, #FRESHVOL, #TOTALVOL, 'A', #EMPCODE, GETDATE(), #CARRYOVERVOL)
SELECT '1'
END
ELSE
BEGIN
SELECT '0'
END
END
but the problem is that if the TARGET_DT is given as future date, it executes the else condition, I want it to execute the if condition, the above is the code which I tired. Any help in solving this will be appreciated. Please help.
IF EXISTS(SELECT 1 FROM COD_BLU_OPENING_VOLUME WHERE ((TARGET_DT=CONVERT(DATETIME,GETDATE(),101) OR TARGET_DT>CONVERT(DATETIME,GETDATE(),101)) AND JOBID=#OPENJOB))
BEGIN
IF(SELECT COUNT(1) FROM COD_BLU_INVENTORY WITH(NOLOCK) WHERE (JOBID=#JOB AND STATUS='A' AND (TARGET_DT=CONVERT(DATETIME,GETDATE(),101) OR TARGET_DT>CONVERT(DATETIME,GETDATE(),101))))=0
BEGIN
INSERT INTO COD_BLU_INVENTORY(JOBID,TARGETDT,CARRYOVER,FRESHVOL,TOTALVOL,STATUS,UPDATEDBY,UPDATEDT,OPENINGVOL)
VALUES(#JOB,#TARGETDT,#CARRYOVERVOL,#FRESHVOL,#TOTALVOL,'A',#EMPCODE,GETDATE(),#CARRYOVERVOL)
SELECT '1'
END
ELSE
BEGIN
SELECT'0'
END
END
ELSE IF NOT EXISTS(SELECT 1 FROM COD_BLU_OPENING_VOLUME WHERE ((TARGET_DT=CONVERT(DATETIME,GETDATE(),101) OR TARGET_DT<CONVERT(DATETIME,GETDATE(),101)) AND JOBID=#OPENJOB))
BEGIN
INSERT INTO COD_BLU_OPENING_VOLUME(TARGET_DT,JOBID,OPENING_COUNT,UPDATED_BY,UPDATED_DT,PRE_ASSIGNEDCOUNT)
VALUES(#OPENTARDT,#OPENJOB,#OPENCNT,#OPENEMPCODE,GETDATE(),#PREOPENCNT)
IF (SELECT COUNT(1) FROM COD_BLU_INVENTORY WITH(NOLOCK) WHERE (JOBID=#JOB AND STATUS='A' AND TARGETDT = CONVERT(DATETIME,#TARGETDT,101)))=0
BEGIN
INSERT INTO COD_BLU_INVENTORY(JOBID,TARGETDT,CARRYOVER,FRESHVOL,TOTALVOL,STATUS,UPDATEDBY,UPDATEDT,OPENINGVOL)
VALUES(#JOB,#TARGETDT,#CARRYOVERVOL,#FRESHVOL,#TOTALVOL,'A',#EMPCODE,GETDATE(),#CARRYOVERVOL)
SELECT '1'
END
ELSE
BEGIN
SELECT'0'
END
END
END

SQL Query produces duplicates with "Where IN" query

I have a large SQL statement which does a whole load of joins on my tables. I have converted some of my table relationships to many-to-many relationships so that it is more efficient. I have therefore decided to convert my SQL to do a WHERE IN statement (on location).
The following query is the one that currently returns the desired results:
ALTER PROCEDURE [dbo].[GetMemberListing]
#Locations nvarchar(max)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
select
Member.Id,
AspNetUsers.Salutation,
AspNetUsers.FirstName,
AspNetUsers.PhotoUrl,
AspNetUsers.LastName,
AspNetUsers.Birthday,
AspNetUsers.Gender,
Member.IDType,
Member.JoinDate,
CONCAT (AspNetUsers.FirstName, ' ', AspNetUsers.LastName) as FullName,
AspNetUsers.CountryCode,
AspNetUsers.Email,
Location.Name as LocationName,
AspNetUsers.HomePhone as HomePhone,
coalesce(Package.Name,'No Package') as PackageName,
PackageTerm = case when Package.PackageIsReoccuring = 1 then 'Recurring' when Package.PackageIsSession = 1 then 'Paid In Full' when membership.TotalPrice = 0 then 'Free' when Package.PackagePayInFull = 1 then 'Paid In Full' end,
PackageType.Name as PackageType,
MembershipId = case when membership.id IS NULL THEN '' ELSE 0 end,
coalesce(membershipstate.name, 'N/A') as MembershipState,
MembershipStartDate = case when membership.StartDate IS NULL THEN '' ELSE CONVERT(varchar(50),membership.StartDate) end,
MembershipEndDate = case when membership.EndDate IS NULL THEN '' ELSE CONVERT(varchar(50),membership.EndDate) end
from
(
select
member.id as memberid,
(
select top 1 id
from membership
where memberid = member.id
and membership.StartDate <= getdate()
order by membership.enddate desc
) as membershipid
from member
) as LatestMembership
left join membership
on latestmembership.membershipid = membership.id
join member
on latestmembership.memberid = member.id
join AspNetusers
on member.AspNetUserId = AspNetUsers.Id
join Location
on member.HomeLocationId = Location.Id
left join Package
on membership.packageid = package.Id
left join PackageType
on package.packagetypeid = packagetype.Id
left join MembershipState
on membership.membershipstateid = membershipstate.Id
Order By aspNetusers.LastName desc
END
Below is what i have tried to do; however, it is duplicating the otherwise correct results based on the number of values in the WHERE IN join.
This on member.HomeLocationId = Location.Id
becomes on member.HomeLocationId IN (SELECT Value FROM fn_Split(#Locations, ','))
As seen below:
ALTER PROCEDURE [dbo].[GetMemberListing]
#Locations nvarchar(max)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
select
Member.Id,
AspNetUsers.Salutation,
AspNetUsers.FirstName,
AspNetUsers.PhotoUrl,
AspNetUsers.LastName,
AspNetUsers.Birthday,
AspNetUsers.Gender,
Member.IDType,
Member.JoinDate,
CONCAT (AspNetUsers.FirstName, ' ', AspNetUsers.LastName) as FullName,
AspNetUsers.CountryCode,
AspNetUsers.Email,
Location.Name as LocationName,
AspNetUsers.HomePhone as HomePhone,
coalesce(Package.Name,'No Package') as PackageName,
PackageTerm = case when Package.PackageIsReoccuring = 1 then 'Recurring' when Package.PackageIsSession = 1 then 'Paid In Full' when membership.TotalPrice = 0 then 'Free' when Package.PackagePayInFull = 1 then 'Paid In Full' end,
PackageType.Name as PackageType,
MembershipId = case when membership.id IS NULL THEN '' ELSE 0 end,
coalesce(membershipstate.name, 'N/A') as MembershipState,
MembershipStartDate = case when membership.StartDate IS NULL THEN '' ELSE CONVERT(varchar(50),membership.StartDate) end,
MembershipEndDate = case when membership.EndDate IS NULL THEN '' ELSE CONVERT(varchar(50),membership.EndDate) end
from
(
select member.id as memberid,
(
select top 1 id
from membership
where memberid = member.id
and membership.StartDate <= getdate()
order by membership.enddate desc
) as membershipid
from member
) as LatestMembership
left join membership
on latestmembership.membershipid = membership.id
join member
on latestmembership.memberid = member.id
join AspNetusers
on member.AspNetUserId = AspNetUsers.Id
join Location
on member.HomeLocationId IN (SELECT Value FROM fn_Split(#Locations, ','))
left join Package
on membership.packageid = package.Id
left join PackageType
on package.packagetypeid = packagetype.Id
left join MembershipState
on membership.membershipstateid = membershipstate.Id
Order By aspNetusers.LastName desc
END
Change to using your split function in the where clause. Don't use that function in the join.
In addition you don't really have a valid join condition on the locations table go back to this
on member.HomeLocationId = Location.Id
And later
Where member.HomeLocationId IN (SELECT Value FROM fn_Split(#Locations, ','))

How to improve the code of stored procedure with inner join to possible empty tvp [duplicate]

I want to improve the code of the following stored procedure. I want to join it into single select statement. Can you purpose a better way?
CREATE PROCEDURE [dbo].[pr_FinDocument_Filter]
#finDocIdForFilter [dbo].[GuidList] READONLY,
#filteredSid nvarchar(64),
#filteringOffsetInDay int
AS
BEGIN
IF (#filteredSid is null or #filteringOffsetInDay is null)
BEGIN
RAISERROR(N'arguments must have a value', 15, 1);
END
IF EXISTS (SELECT 1 FROM #finDocIdForFilter)
BEGIN
SELECT fin_doc_extra.docId
FROM
[CpsOther].[dbo].[FinDocumentExtra] AS fin_doc_extra
INNER JOIN #finDocIdForFilter AS fin_doc_for_filter
ON fin_doc_extra.docId = fin_doc_for_filter.Id
AND fin_doc_extra.sid = #filteredSid
WHERE
DATEDIFF(DAY, CONVERT(DATE, fin_doc_extra.value, 105), CONVERT(DATE, GETDATE(), 126)) = #filteringOffsetInDay
END
ELSE
BEGIN
SELECT fin_doc_extra.docId
FROM
[CpsOther].[dbo].[FinDocumentExtra] AS fin_doc_extra
WHERE
fin_doc_extra.sid = #filteredSid
AND DATEDIFF(DAY, CONVERT(DATE, fin_doc_extra.value, 105), CONVERT(DATE, GETDATE(), 126)) = #filteringOffsetInDay
END
END
I think this might work for you.
SELECT fin_doc_extra.docID
FROM [CpsOther].[dbo].[FinDocumentExtra] AS fin_doc_extra
WHERE DATEDIFF(DAY, CONVERT(DATE, fin_doc_extra.value, 105),
CONVERT(DATE, GETDATE(), 126)) = #filteringOffsetInDay
AND fin_doc_extra.sid = #filteredSid
AND ( ( fin_doc_extra.docId IN ( SELECT fin_doc_for_filter.Id
FROM #finDocIdForFilter ) )
OR ( NOT EXISTS ( SELECT 1
FROM #finDocIdForFilter )
)
);
I think that merging 2 selects into one will not necessary improve your code. For comparison, here is an example how you can do that. We have 1 query but it is more complex and can be perceived as less readable.
The query below is based on your your second query. I modified it by adding an additional condition to WHERE statement. This extra condition will be satisfied if #finDocIdForFilter is empty or if #finDocIdForFilter contains matching rows.
SELECT fin_doc_extra.docId
FROM
[CpsOther].[dbo].[FinDocumentExtra] AS fin_doc_extra
WHERE
fin_doc_extra.sid = #filteredSid AND
DATEDIFF(DAY, CONVERT(DATE, fin_doc_extra.value, 105), CONVERT(DATE, GETDATE(), 126)) = #filteringOffsetInDay
AND
(
NOT EXISTS(SELECT 1 FROM #finDocIdForFilter)
OR
EXISTS(
SELECT 1
FROM #finDocIdForFilter AS fin_doc_for_filter
ON fin_doc_extra.docId = fin_doc_for_filter.Ida.AssetCode)
)
I have an idea about left outer join
SELECT TABLEA.Id
FROM
TABLEA
left join TVP
on TVP.Id = TABLEA.Id
WHERE
TABLEA.sid = #filteredSid
AND DATEDIFF(DAY, CONVERT(DATE, TABLEA.value, 105), CONVERT(DATE, GETDATE(), 126)) = #filteringOffsetInDay
AND
(
TVP.Id is not null
OR
NOT EXISTS (SELECT 1 FROM TVP)
)

How to improve the code of stored procedure with inner join to possible empty tvp

I want to improve the code of the following stored procedure. I want to join it into single select statement. Can you purpose a better way?
CREATE PROCEDURE [dbo].[pr_FinDocument_Filter]
#finDocIdForFilter [dbo].[GuidList] READONLY,
#filteredSid nvarchar(64),
#filteringOffsetInDay int
AS
BEGIN
IF (#filteredSid is null or #filteringOffsetInDay is null)
BEGIN
RAISERROR(N'arguments must have a value', 15, 1);
END
IF EXISTS (SELECT 1 FROM #finDocIdForFilter)
BEGIN
SELECT fin_doc_extra.docId
FROM
[CpsOther].[dbo].[FinDocumentExtra] AS fin_doc_extra
INNER JOIN #finDocIdForFilter AS fin_doc_for_filter
ON fin_doc_extra.docId = fin_doc_for_filter.Id
AND fin_doc_extra.sid = #filteredSid
WHERE
DATEDIFF(DAY, CONVERT(DATE, fin_doc_extra.value, 105), CONVERT(DATE, GETDATE(), 126)) = #filteringOffsetInDay
END
ELSE
BEGIN
SELECT fin_doc_extra.docId
FROM
[CpsOther].[dbo].[FinDocumentExtra] AS fin_doc_extra
WHERE
fin_doc_extra.sid = #filteredSid
AND DATEDIFF(DAY, CONVERT(DATE, fin_doc_extra.value, 105), CONVERT(DATE, GETDATE(), 126)) = #filteringOffsetInDay
END
END
I think this might work for you.
SELECT fin_doc_extra.docID
FROM [CpsOther].[dbo].[FinDocumentExtra] AS fin_doc_extra
WHERE DATEDIFF(DAY, CONVERT(DATE, fin_doc_extra.value, 105),
CONVERT(DATE, GETDATE(), 126)) = #filteringOffsetInDay
AND fin_doc_extra.sid = #filteredSid
AND ( ( fin_doc_extra.docId IN ( SELECT fin_doc_for_filter.Id
FROM #finDocIdForFilter ) )
OR ( NOT EXISTS ( SELECT 1
FROM #finDocIdForFilter )
)
);
I think that merging 2 selects into one will not necessary improve your code. For comparison, here is an example how you can do that. We have 1 query but it is more complex and can be perceived as less readable.
The query below is based on your your second query. I modified it by adding an additional condition to WHERE statement. This extra condition will be satisfied if #finDocIdForFilter is empty or if #finDocIdForFilter contains matching rows.
SELECT fin_doc_extra.docId
FROM
[CpsOther].[dbo].[FinDocumentExtra] AS fin_doc_extra
WHERE
fin_doc_extra.sid = #filteredSid AND
DATEDIFF(DAY, CONVERT(DATE, fin_doc_extra.value, 105), CONVERT(DATE, GETDATE(), 126)) = #filteringOffsetInDay
AND
(
NOT EXISTS(SELECT 1 FROM #finDocIdForFilter)
OR
EXISTS(
SELECT 1
FROM #finDocIdForFilter AS fin_doc_for_filter
ON fin_doc_extra.docId = fin_doc_for_filter.Ida.AssetCode)
)
I have an idea about left outer join
SELECT TABLEA.Id
FROM
TABLEA
left join TVP
on TVP.Id = TABLEA.Id
WHERE
TABLEA.sid = #filteredSid
AND DATEDIFF(DAY, CONVERT(DATE, TABLEA.value, 105), CONVERT(DATE, GETDATE(), 126)) = #filteringOffsetInDay
AND
(
TVP.Id is not null
OR
NOT EXISTS (SELECT 1 FROM TVP)
)

T-SQL ERROR - Subquery returned more than 1 value

I am getting the following error in SQL Server:
Msg 512, Level 16, State 1, Line 18 Subquery returned more than 1
value. This is not permitted when the subquery follows =, !=, <, <= , > >, >= or when the subquery is used as an expression.
My code is as follows:
DECLARE
#personNumber varchar(20),
#itemNumber varchar(20)
SET #personNumber = 'null'
SET #itemNumber = 'null'
SELECT
OU.UserID
,OU.Name
,IGWQ.itemNumber
,IG.itemName
,IGWQ.QuantityOnHand
FROM dbo.Table1 IGWQ
INNER JOIN Table2 OU ON IGWQ.UserId = OU.UserId
INNER JOIN Table3 IG ON IGWQ.itemNumber = IG.itemNumber
WHERE IGWQ.userid IN (CASE WHEN #personNumber = 'null'
THEN ( SELECT DISTINCT
UserID
FROM Table2 WITH(NOLOCK)
WHERE [Role] = '01')
ELSE #personNumber
END)
AND IGWQ.itemNumber IN (CASE WHEN #itemNumber = 'null'
THEN ( SELECT DISTINCT
itemNumber
FROM dbo.Table1 WITH(NOLOCK))
ELSE #itemNumber
END)
Can anyone suggest a solution to this problem? I thought using 'IN' would have fixed the issue.
use this to fix the rest:
WHERE ((#personNumber <> 'null' AND #personNumber = IGWQ.userid)
OR (#personNumber = 'null' AND IGWQ.userid IN ( SELECT UserID
FROM Table2 WITH(NOLOCK)
WHERE [Role] = '01')
))
You don't need the DISTINCT as the IN statement only handles distinct values.
WHERE (IGWQ.userid = #personNumber OR
#personNumber = 'NULL' and
EXISTS (SELECT *
FROM Table2 t WITH (NOLOCK)
WHERE t.[Role] = '01' AND t.UserID = IGWQ.userid)
)
AND (IGWQ.itemNumber = #itemNumber OR
#itemNumber = 'NULL' and
EXISTS (SELECT *
FROM dbo.Table1 t WITH (NOLOCK)
WHERE t.itemNumber = IGWQ.itemNumber)
)
Notes:
CASE returns a scalar, it cannot return a subquery (i.e. set).
WITH (NOLOCK) is deprecated. change the connection isolation to READ UNCOMMITTED or SNAPSHOT instead.

Resources