CASE WHEN to assign a result set to a query - sql

I've been trying to assign different resultsets to a query depending on an input
Depending on the company selected a set of filtered results should be displayed, here's my code.
DECLARE #COMPANY VARCHAR(10) = 'Company_name1'
SELECT
(CASE
WHEN #COMPANY = 'Company_name1'
THEN (SELECT INVENTLOCATIONID FROM INVENTDIM INV
WHERE (INV.DATAAREAID = #COMPANY)
AND (((INVENTLOCATIONID IS NOT NULL)
AND ((WMSLOCATIONID IS NOT NULL)
AND (WMSLOCATIONID <> '')))
AND (INV.INVENTLOCATIONID = 'x5'))
WHEN #COMPANY = 'Company_name2'
THEN (SELECT INVENTLOCATIONID FROM INVENTDIM INV
WHERE (INV.DATAAREAID = #COMPANY)
AND (((INVENTLOCATIONID IS NOT NULL)
AND ((WMSLOCATIONID IS NOT NULL)
AND (WMSLOCATIONID <> '')))
AND (INVENTLOCATIONID IN ('X0', 'X1', 'X2', 'X3', 'X5', 'X6', 'X8', 'P6', 'P8')))
ELSE (SELECT INVENTLOCATIONID FROM INVENTDIM INV
WHERE (DATAAREAID = #COMPANY)
AND ((INVENTLOCATIONID IS NOT NULL)
AND ((WMSLOCATIONID IS NOT NULL)
AND (WMSLOCATIONID <> '')))
END) AS WHAREWOUSE
FROM
INVENTDIM INV
ORDER BY
INV.INVENTLOCATIONID
Why am I not allowed to do this?

Here's one way you could do this using a CASE expression. Use a constant to reject entries where the company name matches the specific cases and the location is not in your list. If the company isn't one of the special cases, then accept it.
DECLARE #COMPANY VARCHAR(10) = 'Company_name1';
SELECT WHAREHOUSE = INVENTLOCATIONID
FROM dbo.INVENTDIM
WHERE DATAAREAID = #COMPANY
AND INVENTLOCATIONID IS NOT NULL
AND WMSLOCATIONID IS NOT NULL
AND WMSLOCATIONID <> ''
AND 1 =
(
CASE
WHEN DATAAREAID = 'Company_name1'
AND INVENTLOCATIONID <> 'x5'
THEN 0
WHEN DATAAREAID = 'Company_name2'
AND INVENTLOCATIONID NOT IN ('X0','X1','X2','X3','X5','X6','X8','P6','P8')
THEN 0
ELSE 1
END
)
ORDER BY INVENTLOCATIONID;
Potentially a disaster for query plan reuse, though, unless DATAAREAID is unique.
This is definitely a better approach:
Can you create a new cross reference table to allow the database to map company to the inventlocationid? – Zynon Putney II
So say you had a mapping table like:
CREATE TABLE dbo.LocationMap
(
DATAAREAID varchar(10),
INVENTLOCATIONID char(2),
PRIMARY KEY(DATAAREAID, INVENTLOCATIONID
);
INSERT dbo.LocationMap(DATAAREAID,INVENTLOCATIONID)
VALUES
('Company_Name1', 'x5'),
('Company_Name2', 'X0'), ('Company_Name2', 'X1') -- , ...
Then your query becomes:
DECLARE #COMPANY VARCHAR(10) = 'Company_name1';
SELECT WHAREHOUSE = INV.INVENTLOCATIONID
FROM dbo.INVENTDIM AS INV
LEFT OUTER JOIN dbo.LocationMap AS lm
ON INV.DATAAREAID = lm.DATAAREAID
WHERE INV.DATAAREAID = #COMPANY
AND INV.INVENTLOCATIONID IS NOT NULL
AND INV.WMSLOCATIONID IS NOT NULL
AND INV.WMSLOCATIONID <> ''
AND (lm.INVENTLOCATIONID = INV.INVENTLOCATIONID
OR lm.DATAAREAID IS NULL)
ORDER BY INV.INVENTLOCATIONID;

Written as a single query this is equivalent logic. Depending on the size of your data it's possible that the if..else branching would work better.
SELECT INVENTLOCATINID
FROM INVENTDIM INV
WHERE
INV.DATAAREAID = #COMPANY AND INVENTLOCATIONID IS NOT NULL WMSLOCATIONID <> '' AND
(
#COMPANY = 'Company name1' AND INV.INVENTLOCATIONID = 'x5' OR
#COMPANY = 'Company_name2' AND INVENTLOCATIONID IN
('X0', 'X1','X2','X3','X5','X6','X8','P6','P8') OR
#COMPANY NOT IN ('Company name1', 'Company name2')
);

Try this below query to get desired output
DECLARE #COMPANY VARCHAR(10) = 'Company_name1'
declare #tblIL as table
(
INVENTLOCATIONID int
)
IF(#COMPANY = 'Company_name1')
BEGIN
insert into #tblIL(INVENTLOCATIONID) values ('x5')
END
ELSE IF(#COMPANY = 'Company_name2')
BEGIN
insert into #tblIL(INVENTLOCATIONID) values ('X0', 'X1','X2','X3','X5','X6','X8','P6','P8')
END
ELSE
BEGIN
insert into #tblIL(INVENTLOCATIONID) values SELECT DISTINCT INVENTLOCATIONID FROM INVENTDIM
END
SELECT INVENTLOCATIONID FROM INVENTDIM INV
WHERE INV.DATAAREAID = #COMPANY AND INVENTLOCATIONID IS NOT NULL AND WMSLOCATIONID IS NOT NULL AND WMSLOCATIONID <> ''
AND INV.INVENTLOCATIONID in (select INVENTLOCATIONID from #tblIL)

Related

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: Update, set a value that is within another select

I have the following query:
update UpdCmmPartnerArticleGroup
set IsActive = 1,
Name = a.GroupName
from
(
select t.Name as GroupName
from #ArticleGroupsTable t
left join UpdCmmPartnerArticleGroup s on s.PartnerID=t.PartnerID and s.Name=t.Name
where s.PartnerID is null
) a
where Name = '' and IsActive = 0
It's purpose is to take a list of GroupNames and assign them to the UpdCmmPartnerArticleGroup.Name field. The list has 8 values and it uses only the first and the last to update.
What am I doing wrong, it looks pretty straight forward, but it's behavior is strange.
You can use a little bit simplified version.
UPDATE u
SET IsActive = 1, Name = t.Name
FROM #ArticleGroupsTable t
LEFT JOIN UpdCmmPartnerArticleGroup u
ON u.PartnerID=t.PartnerID AND u.Name=t.Name
WHERE u.Name = '' and u.IsActive = 0 and u.PartnerID IS NULL
Why not use subquery
update s
set IsActive = 1,
Name = (select t.Name from #ArticleGroupsTable t WHERE s.PartnerID=t.PartnerID and s.Name=t.Name AND s.PartnerID is null)
from UpdCmmPartnerArticleGroup s
where Name = '' and IsActive = 0
Try this,
UPDATE s
SET s.IsActive = 1
,s.NAME = t.NAME
FROM #ArticleGroupsTable t
LEFT JOIN UpdCmmPartnerArticleGroup s ON s.PartnerID = t.PartnerID
AND s.NAME = t.NAME
WHERE s.PartnerID IS NULL
AND s.NAME = ''
AND s.IsActive = 0
Try this:
IF OBJECT_ID('tempdb..#UpdCmmPartnerArticleGroup') IS NOT NULL
DROP TABLE #UpdCmmPartnerArticleGroup;
IF OBJECT_ID('tempdb..#ArticleGroupsTable') IS NOT NULL
DROP TABLE #ArticleGroupsTable;
CREATE TABLE #UpdCmmPartnerArticleGroup
(
PartnerId INT IDENTITY(1, 1)
,Name VARCHAR(50)
,IsActive BIT
);
INSERT INTO [#UpdCmmPartnerArticleGroup]
( [Name], [IsActive] )
VALUES ( 'Test1' -- Name - varchar(50)
, 1 -- IsActive - bit
),
( 'Test2' -- Name - varchar(50)
, 0 -- IsActive - bit
),
( '' -- Name - varchar(50)
, 0 -- IsActive - bit
);
CREATE TABLE #ArticleGroupsTable
(
PartnerId INT
,Name VARCHAR(50)
);
INSERT INTO [#ArticleGroupsTable]
( [PartnerId], [Name] )
VALUES ( 1, 'Test1' ),
( 2, 'Test2' ),
( 4, 'Test4' );
SELECT *
FROM [#UpdCmmPartnerArticleGroup];
SELECT *
FROM [#ArticleGroupsTable];
UPDATE [#UpdCmmPartnerArticleGroup]
SET [IsActive] = 1
, [Name] = (
SELECT t.[Name] AS GroupName
FROM [#ArticleGroupsTable] t
LEFT JOIN [#UpdCmmPartnerArticleGroup] s
ON [s].[PartnerId] = [t].[PartnerId]
AND [s].[Name] = [t].[Name]
WHERE [s].[PartnerId] IS NULL
)
WHERE [#UpdCmmPartnerArticleGroup].[Name] = ''
AND [IsActive] = 0;
SELECT *
FROM [#UpdCmmPartnerArticleGroup];

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

COALESCE... Can anybody help me to optimize this code?

Can anybody help me to optimize this code? At present it takes 17 seconds.
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO
--SpResumeSearch NULL,null,null,null,null,null,null,null,null,null,null,NULL,null,null,null,null,null,null,null,0,10,NULL
ALTER PROCEDURE [dbo].[SpResumeSearch]
#Keyword varchar(50) = NULL,
#JobCategoryId int = NULL,
#NationalityId int = NULL,
#CountryId int = NULL,
#LocationId int = NULL,
#Email nvarchar(50) = NULL,
#Gender int = NULL,
#PassportNumber nvarchar(20) = NULL,
#VisaStatus int = NULL,
#PoBox nvarchar(10) = NULL,
#CareerLevelId int = NULL,
#KeySkills nvarchar(50) = NULL,
#ExpectedSalary int = NULL,
#Experience int = NULL,
#DOB varchar(20) = NULL,
#AppliedFrom datetime = NULL,
#AppliedTo datetime = NULL,
#MaritalStatusId int = NULL,
#LanguageId int = NULL,
#PageIndex int,
#NumRows int,
#SortCol varchar(20) = NULL
AS
BEGIN
DECLARE #startRowIndex INT;
SET #startRowIndex = (#PageIndex * #NumRows) + 1;
WITH ResumeListTemp AS
(SELECT DISTINCT M.MemberID, R.ResumeID, R.CreatedDate, R.ModifiedDate, R.CompletedDate, RP.FirstName, RP.LastName, G.Title AS Gender,
RP.DateOfBirth, C.NationalityTitle AS Nationality, RPD.KeySkills, RPD.ExperienceYear AS Experience, V.Title AS VisaStatus, RC.Phone, RC.Mobile,
ROW_NUMBER() OVER (ORDER BY
CASE WHEN #SortCol='FIRSTNAME' THEN FirstName END,
CASE WHEN #SortCol='LASTNAME' THEN RP.LastName END,
CASE WHEN #SortCol='GENDER' THEN G.Title END,
CASE WHEN #SortCol='DOB' THEN RP.DateOfBirth END,
CASE WHEN #SortCol='NATIONALITY' THEN C.NationalityTitle END,
CASE WHEN #SortCol='KEYSKILLS' THEN RPD.KeySkills END,
CASE WHEN #SortCol='EXPERIENCE' THEN RPD.ExperienceYear END,
CASE WHEN #SortCol='VISASTATUS' THEN V.Title END,
CASE WHEN #SortCol='CONTACTNO' THEN RC.Mobile END,
CASE WHEN #SortCol='UPDATEDATE' THEN R.ModifiedDate END,
CASE WHEN #SortCol IS NULL THEN R.CompletedDate END
) AS RowNum
FROM TblResume AS R
LEFT OUTER JOIN TblResumeContactInfo AS RC ON RC.FKResumeID = R.ResumeID
LEFT OUTER JOIN TblResumePersonalDetail AS RP ON RP.FKResumeID = R.ResumeID
LEFT OUTER JOIN TblResumeJobCategory AS RJC ON RJC.FKResumeID = R.ResumeID
LEFT OUTER JOIN TblResumeProfessionalDetail AS RPD ON RPD.FKResumeID = R.ResumeID
LEFT OUTER JOIN TblResumeWorkExperience AS RE ON RE.FKResumeID = R.ResumeID
LEFT OUTER JOIN TblResumeEducation AS RQ ON RQ.FKResumeID = R.ResumeID
LEFT OUTER JOIN TblResumeSkill AS RS ON RS.FKResumeID = R.ResumeID
LEFT OUTER JOIN TblMember AS M ON M.MemberID = R.FKMemberID
LEFT OUTER JOIN TblMasterGender AS G ON G.GenderID = RP.FKGenderID
LEFT OUTER JOIN TblMasterCountry AS C ON C.CountryID = RP.FKNationalityID
LEFT OUTER JOIN TblRisVisaStatus AS V ON V.VisaStatusID = RP.FKVisaStatusID
LEFT OUTER JOIN TblResumeLanguage AS L ON L.FKResumeID = R.ResumeID
WHERE (
-- RC.Address LIKE '%'+COALESCE(#Keyword,RC.Address)+'%' OR
-- RC.City LIKE '%'+COALESCE(#Keyword,RC.City)+'%' OR
R.ResumeID IN ( SELECT _RQ.FKResumeID FROM TblResumeEducation AS _RQ, TblResume AS _R WHERE _RQ.Specialization LIKE '%'+COALESCE(#Keyword, _RQ.Specialization)+'%' AND _RQ.FKResumeID=_R.ResumeID GROUP BY _RQ.FKResumeID) OR
R.ResumeID IN ( SELECT _RQ.FKResumeID FROM TblResumeEducation AS _RQ, TblResume AS _R WHERE _RQ.Institution LIKE '%'+COALESCE(#Keyword, _RQ.Institution)+'%' AND _RQ.FKResumeID=_R.ResumeID GROUP BY _RQ.FKResumeID) OR
RP.FirstName LIKE '%'+COALESCE(#Keyword,RP.FirstName)+'%' OR
RP.LastName LIKE '%'+COALESCE(#Keyword,RP.LastName)+'%' OR
--RP.PassportNumber LIKE '%'+COALESCE(#Keyword,RP.PassportNumber)+'%' OR
--(#Keyword IS NULL OR RP.PassportNumber LIKE '%' + #Keyword +'%') OR
RPD.Summary LIKE '%'+COALESCE(#Keyword,RPD.Summary)+'%' OR
-- R.ResumeID IN ( SELECT _RS.FKResumeID FROM TblResumeSkill AS _RS, TblResume AS _R WHERE _RS.Title LIKE '%'+COALESCE(#Keyword,_RS.Title)+'%' AND _RS.FKResumeID=_R.ResumeID GROUP BY _RS.FKResumeID) OR
-- R.ResumeID IN ( SELECT _RE.FKResumeID FROM TblResumeWorkExperience AS _RE, TblResume AS _R WHERE _RE.Employer LIKE '%'+COALESCE(#Keyword, _RE.Employer)+'%' AND _RE.FKResumeID=_R.ResumeID GROUP BY _RE.FKResumeID) OR
R.ResumeID IN ( SELECT _RE.FKResumeID FROM TblResumeWorkExperience AS _RE, TblResume AS _R WHERE _RE.Designation LIKE '%'+COALESCE(#Keyword, _RE.Designation)+'%' AND _RE.FKResumeID=_R.ResumeID GROUP BY _RE.FKResumeID) OR
R.ResumeID IN ( SELECT _RE.FKResumeID FROM TblResumeWorkExperience AS _RE, TblResume AS _R WHERE _RE.Responsibilities LIKE '%'+COALESCE(#Keyword, _RE.Responsibilities)+'%' AND _RE.FKResumeID=_R.ResumeID GROUP BY _RE.FKResumeID)) AND
R.ResumeID IN ( SELECT _RJC.FKResumeID FROM TblResumeJobCategory AS _RJC, TblResume AS _R WHERE _RJC.FKJobCategoryID = COALESCE(#JobCategoryId, _RJC.FKJobCategoryID) AND _RJC.FKResumeID=_R.ResumeID GROUP BY _RJC.FKResumeID ) AND
RP.FKNationalityID = COALESCE(#NationalityId, RP.FKNationalityID) AND
RC.FKCountryID = COALESCE(#CountryId, RC.FKCountryID) AND
-- RPD.FKJobLocationID = COALESCE(#LocationId, RPD.FKJobLocationID) AND
-- M.Email LIKE '%'+COALESCE(#Email, M.Email)+'%' AND
-- RP.FKGenderID = COALESCE(#Gender, RP.FKGenderID) AND
-- RP.PassportNumber LIKE '%'+COALESCE(#PassportNumber, RP.PassportNumber)+'%' AND
-- RP.FKVisaStatusID = COALESCE(#VisaStatus, RP.FKVisaStatusID) AND
-- COALESCE(RC.ZipCode,'0') LIKE '%'+COALESCE(#PoBox, COALESCE(RC.ZipCode,'0'))+'%' AND
RPD.FKExperienceLevelID = COALESCE(#CareerLevelId, RPD.FKExperienceLevelID) AND
-- RPD.KeySkills LIKE '%'+COALESCE(#KeySkills, RPD.KeySkills)+'%' AND
RPD.FKSalaryID = COALESCE(#ExpectedSalary, RPD.FKSalaryID) AND
RPD.ExperienceYear = COALESCE(#Experience, RPD.ExperienceYear) AND
RP.DateOfBirth = COALESCE(#DOB, RP.DateOfBirth) AND
R.CompletedDate = COALESCE(#AppliedFrom, R.CompletedDate) AND
R.CompletedDate = COALESCE(#AppliedTo, R.CompletedDate) AND
RP.FKMaritalStatusID = COALESCE(#MaritalStatusId, RP.FKMaritalStatusID) AND
R.ResumeID IN ( SELECT _L.FKResumeID FROM TblResumeLanguage AS _L, TblResume AS _R WHERE _L.FKLanguageID = COALESCE(#LanguageId, _L.FKLanguageID) AND _L.FKResumeID=_R.ResumeID GROUP BY _L.FKResumeID ) AND
R.IsCompleted = 1
)
SELECT ResumeListTemp.*, (SELECT COUNT(*) from ResumeListTemp) AS RecCount
FROM ResumeListTemp
WHERE RowNum BETWEEN #startRowIndex AND #StartRowIndex + #NumRows - 1
ORDER BY
CASE WHEN #SortCol='FIRSTNAME' THEN FirstName END,
CASE WHEN #SortCol='LASTNAME' THEN LastName END,
CASE WHEN #SortCol='GENDER' THEN Gender END,
CASE WHEN #SortCol='DOB' THEN DateOfBirth END,
CASE WHEN #SortCol='NATIONALITY' THEN Nationality END,
CASE WHEN #SortCol='KEYSKILLS' THEN KeySkills END,
CASE WHEN #SortCol='EXPERIENCE' THEN Experience END,
CASE WHEN #SortCol='VISASTATUS' THEN VisaStatus END,
CASE WHEN #SortCol='CONTACTNO' THEN Mobile END,
CASE WHEN #SortCol='UPDATEDATE' THEN ModifiedDate END,
CASE WHEN #SortCol IS NULL THEN CompletedDate END
END
try to replace * with the column names
In this case, I think that building your query dynamically and using sp_executesql will give you much better performance.
There's an MSDN article explaining the basics here, and there are some more in-depth articles by Erland Sommarskog, here and here.
Having '%' at the very start of a LIKE clause can cause a table scan, try to remove them if possible.
since there is only one column to be sorted in the result, you may try to replace the ORDER BY clause (twice!) as
CASE #SortCol
WHEN 'FIRSTNAME' THEN FirstName
WHEN 'LASTNAME' THEN LastName
etc
ELSE CompletedDate
END
(you probably need to CONVERT columns to NVARCHAR)
Optimization for WHERE section - seems to me, there is no need of using IN clause, thouse tables are already joined by ResumeID, all you need is to filter them out:
WHERE (
(RQ.Specialization IS NOT NULL AND (#Keyword IS NULL OR RQ.Specialization LIKE '%'+#Keyword+'%')) OR
(RQ.Institution IS NOT NULL AND (#Keyword IS NULL OR RQ.Institution LIKE '%'+#Keyword+'%')) OR
(RP.FirstName IS NOT NULL AND (#Keyword IS NULL OR RP.FirstName LIKE '%'+#Keyword+'%')) OR
(RP.LastName IS NOT NULL AND (#Keyword IS NULL OR RP.LastName LIKE '%'+#Keyword+'%')) OR
(RPD.Summary IS NOT NULL AND (#Keyword IS NULL OR RPD.Summary LIKE '%'+#Keyword+'%')) OR
(RE.Designation IS NOT NULL AND (#Keyword IS NULL OR RE.Designation LIKE '%'+#Keyword+'%')) OR
(RE.Responsibilities IS NOT NULL AND (#Keyword IS NULL OR RE.Responsibilities LIKE '%'+#Keyword+'%'))) AND
(RJC.FKJobCategoryID IS NOT NULL AND (#JobCategoryId IS NULL OR RE.Designation LIKE '%'+#JobCategoryId+'%')) AND
RP.FKNationalityID = COALESCE(#NationalityId, RP.FKNationalityID) AND
RC.FKCountryID = COALESCE(#CountryId, RC.FKCountryID) AND
RPD.FKExperienceLevelID = COALESCE(#CareerLevelId, RPD.FKExperienceLevelID) AND
RPD.FKSalaryID = COALESCE(#ExpectedSalary, RPD.FKSalaryID) AND
RPD.ExperienceYear = COALESCE(#Experience, RPD.ExperienceYear) AND
RP.DateOfBirth = COALESCE(#DOB, RP.DateOfBirth) AND
R.CompletedDate = COALESCE(#AppliedFrom, R.CompletedDate) AND
R.CompletedDate = COALESCE(#AppliedTo, R.CompletedDate) AND
RP.FKMaritalStatusID = COALESCE(#MaritalStatusId, RP.FKMaritalStatusID) AND
(L.FKLanguageID IS NOT NULL AND (#LanguageId IS NULL OR L.FKLanguageID LIKE '%'+#LanguageId+'%')) AND
R.IsCompleted = 1
)
Why are you starting each where clause with a wildcard? you can never optimize using that technique (even if you convert to dynamic SQL) as the database is not unable to use the indexes. Require your users to to at a minimum put in the first letter of what they are searching for.
Get rid of the subselects, they are performance killers. Since you are already joining to those tables, you shouldn't need them.

SQL Switch/Case in 'where' clause

I tried searching around, but I couldn't find anything that would help me out.
I'm trying to do this in SQL:
declare #locationType varchar(50);
declare #locationID int;
SELECT column1, column2
FROM viewWhatever
WHERE
CASE #locationType
WHEN 'location' THEN account_location = #locationID
WHEN 'area' THEN xxx_location_area = #locationID
WHEN 'division' THEN xxx_location_division = #locationID
I know that I shouldn't have to put '= #locationID' at the end of each one, but I can't get the syntax even close to being correct. SQL keeps complaining about my '=' on the first WHEN line...
How can I do this?
declare #locationType varchar(50);
declare #locationID int;
SELECT column1, column2
FROM viewWhatever
WHERE
#locationID =
CASE #locationType
WHEN 'location' THEN account_location
WHEN 'area' THEN xxx_location_area
WHEN 'division' THEN xxx_location_division
END
without a case statement...
SELECT column1, column2
FROM viewWhatever
WHERE
(#locationType = 'location' AND account_location = #locationID)
OR
(#locationType = 'area' AND xxx_location_area = #locationID)
OR
(#locationType = 'division' AND xxx_location_division = #locationID)
Here you go.
SELECT
column1,
column2
FROM
viewWhatever
WHERE
CASE
WHEN #locationType = 'location' AND account_location = #locationID THEN 1
WHEN #locationType = 'area' AND xxx_location_area = #locationID THEN 1
WHEN #locationType = 'division' AND xxx_location_division = #locationID THEN 1
ELSE 0
END = 1
I'd say this is an indicator of a flawed table structure. Perhaps the different location types should be separated in different tables, enabling you to do much richer querying and also avoid having superfluous columns around.
If you're unable to change the structure, something like the below might work:
SELECT
*
FROM
Test
WHERE
Account_Location = (
CASE LocationType
WHEN 'location' THEN #locationID
ELSE Account_Location
END
)
AND
Account_Location_Area = (
CASE LocationType
WHEN 'area' THEN #locationID
ELSE Account_Location_Area
END
)
And so forth... We can't change the structure of the query on the fly, but we can override it by making the predicates equal themselves out.
EDIT: The above suggestions are of course much better, just ignore mine.
The problem with this is that when the SQL engine goes to evaluate the expression, it checks the FROM portion to pull the proper tables, and then the WHERE portion to provide some base criteria, so it cannot properly evaluate a dynamic condition on which column to check against.
You can use a WHERE clause when you're checking the WHERE criteria in the predicate, such as
WHERE account_location = CASE #locationType
WHEN 'business' THEN 45
WHEN 'area' THEN 52
END
so in your particular case, you're going to need put the query into a stored procedure or create three separate queries.
OR operator can be alternative of case when in where condition
ALTER PROCEDURE [dbo].[RPT_340bClinicDrugInventorySummary]
-- Add the parameters for the stored procedure here
#ClinicId BIGINT = 0,
#selecttype int,
#selectedValue varchar (50)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
SELECT
drugstock_drugname.n_cur_bal,drugname.cdrugname,clinic.cclinicname
FROM drugstock_drugname
INNER JOIN drugname ON drugstock_drugname.drugnameid_FK = drugname.drugnameid_PK
INNER JOIN drugstock_drugndc ON drugname.drugnameid_PK = drugstock_drugndc.drugnameid_FK
INNER JOIN drugndc ON drugstock_drugndc.drugndcid_FK = drugndc.drugid_PK
LEFT JOIN clinic ON drugstock_drugname.clinicid_FK = clinic.clinicid_PK
WHERE (#ClinicId = 0 AND 1 = 1)
OR (#ClinicId != 0 AND drugstock_drugname.clinicid_FK = #ClinicId)
-- Alternative Case When You can use OR
AND ((#selecttype = 1 AND 1 = 1)
OR (#selecttype = 2 AND drugname.drugnameid_PK = #selectedValue)
OR (#selecttype = 3 AND drugndc.drugid_PK = #selectedValue)
OR (#selecttype = 4 AND drugname.cdrugclass = 'C2')
OR (#selecttype = 5 AND LEFT(drugname.cdrugclass, 1) = 'C'))
ORDER BY clinic.cclinicname, drugname.cdrugname
END
Please try this query.
Answer To above post:
select #msgID, account_id
from viewMailAccountsHeirachy
where
CASE #smartLocationType
WHEN 'store' THEN account_location
WHEN 'area' THEN xxx_location_area
WHEN 'division' THEN xxx_location_division
WHEN 'company' THEN xxx_location_company
END = #smartLocation
Try this:
WHERE (
#smartLocationType IS NULL
OR account_location = (
CASE
WHEN #smartLocationType IS NOT NULL
THEN #smartLocationType
ELSE account_location
END
)
)
CREATE PROCEDURE [dbo].[Temp_Proc_Select_City]
#StateId INT
AS
BEGIN
SELECT * FROM tbl_City
WHERE
#StateID = CASE WHEN ISNULL(#StateId,0) = 0 THEN 0 ELSE StateId END ORDER BY CityName
END
Try this query, it's very easy and useful: Its ready to execute!
USE tempdb
GO
IF NOT OBJECT_ID('Tempdb..Contacts') IS NULL
DROP TABLE Contacts
CREATE TABLE Contacts(ID INT, FirstName VARCHAR(100), LastName VARCHAR(100))
INSERT INTO Contacts (ID, FirstName, LastName)
SELECT 1, 'Omid', 'Karami'
UNION ALL
SELECT 2, 'Alen', 'Fars'
UNION ALL
SELECT 3, 'Sharon', 'b'
UNION ALL
SELECT 4, 'Poja', 'Kar'
UNION ALL
SELECT 5, 'Ryan', 'Lasr'
GO
DECLARE #FirstName VARCHAR(100)
SET #FirstName = 'Omid'
DECLARE #LastName VARCHAR(100)
SET #LastName = ''
SELECT FirstName, LastName
FROM Contacts
WHERE
FirstName = CASE
WHEN LEN(#FirstName) > 0 THEN #FirstName
ELSE FirstName
END
AND
LastName = CASE
WHEN LEN(#LastName) > 0 THEN #LastName
ELSE LastName
END
GO
In general you can manage case of different where conditions in this way
SELECT *
FROM viewWhatever
WHERE 1=(CASE <case column or variable>
WHEN '<value1>' THEN IIF(<where condition 1>,1,0)
WHEN '<value2>' THEN IIF(<where condition 2>,1,0)
ELSE IIF(<else condition>,1,0)
END)
Case Statement in SQL Server Example
Syntax
CASE [ expression ]
WHEN condition_1 THEN result_1
WHEN condition_2 THEN result_2
...
WHEN condition_n THEN result_n
ELSE result
END
Example
SELECT contact_id,
CASE website_id
WHEN 1 THEN 'TechOnTheNet.com'
WHEN 2 THEN 'CheckYourMath.com'
ELSE 'BigActivities.com'
END
FROM contacts;
OR
SELECT contact_id,
CASE
WHEN website_id = 1 THEN 'TechOnTheNet.com'
WHEN website_id = 2 THEN 'CheckYourMath.com'
ELSE 'BigActivities.com'
END
FROM contacts;
This worked for me.
CREATE TABLE PER_CAL ( CAL_YEAR INT, CAL_PER INT )
INSERT INTO PER_CAL( CAL_YEAR, CAL_PER ) VALUES ( 20,1 ), ( 20,2 ), ( 20,3 ), ( 20,4 ), ( 20,5 ), ( 20,6 ), ( 20,7 ), ( 20,8 ), ( 20,9 ), ( 20,10 ), ( 20,11 ), ( 20,12 ),
( 99,1 ), ( 99,2 ), ( 99,3 ), ( 99,4 ), ( 99,5 ), ( 99,6 ), ( 99,7 ), ( 99,8 ), ( 99,9 ), ( 99,10 ), ( 99,11 ), ( 99,12 )
The 4 digit century is determined by the rule, if the year is 50 or more, the century is 1900, otherwise 2000.
Given two 6 digit periods that mark the start and end period, like a quarter, return the rows that fall in that range.
-- 1st quarter of 2020
SELECT * FROM PER_CAL WHERE (( CASE WHEN CAL_YEAR > 50 THEN 1900 ELSE 2000 END + CAL_YEAR ) * 100 + CAL_PER ) BETWEEN 202001 AND 202003
-- 4th quarter of 1999
SELECT * FROM PER_CAL WHERE (( CASE WHEN CAL_YEAR > 50 THEN 1900 ELSE 2000 END + CAL_YEAR ) * 100 + CAL_PER ) BETWEEN 199910 AND 199912
Try this query. Its very easy to understand:
CREATE TABLE PersonsDetail(FirstName nvarchar(20), LastName nvarchar(20), GenderID int);
GO
INSERT INTO PersonsDetail VALUES(N'Gourav', N'Bhatia', 2),
(N'Ramesh', N'Kumar', 1),
(N'Ram', N'Lal', 2),
(N'Sunil', N'Kumar', 3),
(N'Sunny', N'Sehgal', 1),
(N'Malkeet', N'Shaoul', 3),
(N'Jassy', N'Sohal', 2);
GO
SELECT FirstName, LastName, Gender =
CASE GenderID
WHEN 1 THEN 'Male'
WHEN 2 THEN 'Female'
ELSE 'Unknown'
END
FROM PersonsDetail