checking if condition in stored procedure( sql server 2005) - sql-server-2005

i have an SP where i need to check for if condition
ALTER PROCEDURE [dbo].[spCheck]
#strEmpname VARCHAR(50),
#intReturn INT OUTPUT,
#intWorkdID INT,
#intEmpID INT
AS
BEGIN
IF(#intWorkdID is not null and #intWorkdID != '')
BEGIN
IF EXISTS ( SELECT *
FROM Employee
WHERE [Empname] = #strEmpname
AND WorkID = #intWorkdID
)
SELECT #intReturn = '1'
END
ELSE
IF(#intEmpID is not null and #intEmpID != '')
BEGIN
IF EXISTS ( SELECT *
FROM Employee
WHERE [Empname] = #strEmpname
AND PeopleID = #intEmpID
)
SELECT #intReturn = '1'
END
ELSE IF(#intEmpID is not null and #intEmpID != '')
and(#intWorkdID is not null and #intWorkdID != '')
BEGIN
SELECT #intReturn = '0'
END
END
here based on WorkID,EmpID
1 condition and 2 condition should execute
if both condition fail i need to excute the third condition
can any one tell the syntax for it
thanks
prince

Best way is that you can use
Try something as below:
SELECT #intReturn =
CASE
WHEN #intWorkdID IS NULL THEN 1
WHEN #intWorkdID<>'' THEN 1
WHEN #intEmpID IS NULL THEN 1
WHEN #intEmpID <>'' THEN 1
ELSE 0
END
Case... When
for this

An int can't equal ''.
I'm not sure what you're asking for in your logic, but when an if doesn't match then it runs the else part. You can then have anpther if -> else after that as per your script.

Related

SQL Server - Using CASE statement

I have a SELECT statement with a WHERE clause that I want to dynamically change depending if a parameter is supplied or not.
I can't seem to understand how to use CASE statement in a WHERE clause but this is how I want it to look like using an IF statement.
DECLARE #Gender NVARCHAR(100) = NULL --this is an INPUT parameter and may or may not be NULL
DECLARE #Status NVARCHAR(100) = NULL --this is an INPUT parameter and may or may not be NULL
SELECT Name
FROM Person
WHERE
-- first WHERE clause
IF #Gender IS NULL
BEGIN
Gender IS NULL
END
ELSE
BEGIN
Gender = #Gender
END
AND
-- second WHERE clause
IF #Status IS NULL
BEGIN
Status IS NULL
END
ELSE
BEGIN
Status LIKE '%' + #Status + '%'
END
Is it possible to transform this code into a CASE statement?
I think you want:
select p.name
from person p
where ( (#gender is null and gender is null) or gender = #gender) and
( (#status is null and status is null) or status = #status);
Note that this does "null-matching". Often, people want to use NULL to select all records, not just the NULL ones. If that is what you intend, then:
select p.name
from person p
where ( #gender is null or gender = #gender) and
( #status is null or status = #status);
In either situation, case is not needed in the where. As a general rule, don't use case in where -- unless you really need it to control the order of evaluation of expressions.
You can do this:
SELECT Name
FROM Person
WHERE Gender = COALESCE(#gender, Gender)
AND (#Status is null or Status like '%' + #status + '%')
DECLARE #Gender NVARCHAR(100) = NULL --this is an INPUT parameter and may or may not be NULL
DECLARE #Status NVARCHAR(100) = NULL --this is an INPUT parameter and may or may not be NULL
SELECT Name
FROM Person
WHERE CASE WHEN #Gender IS NULL THEN 1
WHEN #Gender = ISNULL(Gender, '') THEN 1
ELSE 0
END = 1
AND CASE WHEN #Status IS NULL THEN 1
WHEN ISNULL(Status, '') LIKE '%' + #Status + '%' THEN 1
ELSE 0
END = 1

SQL CASE wrong output

I have this weird encounter using CASE in sql 2014.
This is my query:
SELECT (CASE WHEN dbo.GetFunctionAge(C.Birthdate) = 0
THEN '' ELSE dbo.GetFunctionAge(C.Birthdate)
END) AS Age
,dbo.GetFunctionAge(C.Birthdate)
,c.Birthdate
FROM Client C
WHERE ClientID = '34d0d845-e3a6-4078-8936-953ff3378eac'
this is the output:
Here is the GetFunctionAge function if you might ask.
IF EXISTS (
SELECT *
FROM dbo.sysobjects
WHERE ID = OBJECT_ID(N'[dbo].[GetFunctionAge]') AND
xtype in (N'FN', N'IF', N'TF'))
DROP FUNCTION [dbo].[GetFunctionAge]
GO
CREATE FUNCTION [dbo].[GetFunctionAge](#BirthDate DATETIME)
RETURNS INT
AS
BEGIN
DECLARE #Age INT
IF(#BirthDate = '1753-01-01 00:00:00.000')
BEGIN
SET #Age = 0
END
ELSE
BEGIN
SET #Age = DATEDIFF(hour,#BirthDate,GETDATE())/8766
END
RETURN #Age
END
GO
Question:
Why is Column Age in my output is 0which should be ''?
I added (No column name) to show that its output is 0 so my expected output base from my case condition is '' not 0
I didn't receive any error regarding inconsistency of data so why is case behaving like that?
Thanks for those who could clarify this to me.
SELECT
(CASE
WHEN a.ageint = 0 THEN ''
ELSE cast(a.ageint as varchar(3))
END) AS Age
, a.ageint
, c.Birthdate
FROM Client as C
CROSS APPLY (
SELECT
ISNULL(dbo.GetFunctionAge(C.Birthdate), 0) AS ageint
) AS a
WHERE ClientID = '34d0d845-e3a6-4078-8936-953ff3378eac'
;
You can cast it into varchar so you can return ' '.
SELECT (CASE WHEN dbo.GetFunctionAge(C.Birthdate) = 0
THEN '' ELSE Cast(dbo.GetFunctionAge(C.Birthdate) as varchar(5))
END) AS Age
,dbo.GetFunctionAge(C.Birthdate)
,c.Birthdate
FROM Client C
WHERE ClientID = '34d0d845-e3a6-4078-8936-953ff3378eac'
But If you wish to remain your Age column in data type int.
You could just use NULL instead of ' '

SQL Server select where most columns match

I have a stored procedure that can have 1 to 4 variables passed to it and it must return the rows where the most columns match or if there are no matching records it returns the default ones (which are null).
The sequence needs to be distinct.
Example table with data:
Client_Id Project_ID Phase Task Employee Sequence
--------- ---------- ----- ---- -------- --------
NULL NULL NULL NULL Chris 1
NULL NULL NULL NULL Bob 100
500 NULL NULL NULL Joe 1
500 2 NULL NULL Max 1
So the results for Client 100, any project, phase or task would simply be the default NULL records of Chris and Bob. For Client 500 the results would be Joe and Bob. For Client 500, Project 2 the result would be Max and Bob.
Right now I am doing this query by checking the task first then joining it with a query by phase and checking that no rows overlap and doing the same for project then client. It seems incredibly inefficient and there has to be a smarter way about this. Any thoughts?
EDIT - Some query examples, I check first for the case where everything matches
insert into #TempTracking
select p.employee, p.sequence
from invoices i, projects p
where i.client_id = p.client_id
and i.project_no = p.project_no
and i.phase = p.phase
and i.task = p.task
Then I make the queries less and less specific and check that the sequence does not already exist.
insert into #TempTracking
select p.employee, p.sequence
from invoices i, projects p
where (i.client_id = p.client_id or i.client_id is null)
and (i.project_no = p.project_no or i.project_no is null)
and (i.phase = p.phase or i.phase is null)
and (i.task = p.task or i.task is null)
and NOT EXISTS ( SELECT * FROM #TempTracking t WHERE t.sequence = p.sequence )
"Most of the columns match" is very vague, but I assume you mean that if they search for null, or if the value in the table is null then assume this record could be included.
If you want the most matching row or all rows that match nothing, then you will need to do something like this (it's starting to get very long)
DECLARE #Client_Id VARCHAR(MAX) = '500'
DECLARE #Project_ID VARCHAR(MAX) = '2'
DECLARE #Phase VARCHAR(MAX) = NULL
DECLARE #Task VARCHAR(MAX) = NULL
SELECT Employee, Sequence
FROM
(SELECT Employee, Sequence,
(
CASE WHEN (Client_Id = #Client_Id OR Client_Id IS NULL OR #Client_Id IS NULL) THEN 1 ELSE 0 END +
CASE WHEN (Project_ID = #Project_ID OR Project_ID IS NULL OR #Project_ID IS NULL) THEN 1 ELSE 0 END +
CASE WHEN (Phase = #Phase OR Phase IS NULL OR #Phase IS NULL) THEN 1 ELSE 0 END +
CASE WHEN (Task = #Task OR Task IS NULL OR #Task IS NULL) THEN 1 ELSE 0 END
) AS MatchCount
WHERE MatchCount =
(
SELECT MAX(
CASE WHEN (Client_Id = #Client_Id OR Client_Id IS NULL OR #Client_Id IS NULL) THEN 1 ELSE 0 END +
CASE WHEN (Project_ID = #Project_ID OR Project_ID IS NULL OR #Project_ID IS NULL) THEN 1 ELSE 0 END +
CASE WHEN (Phase = #Phase OR Phase IS NULL OR #Phase IS NULL) THEN 1 ELSE 0 END +
CASE WHEN (Task = #Task OR Task IS NULL OR #Task IS NULL) THEN 1 ELSE 0 END
)
FROM myTable
)
-- Now prevent for duplicate sequence numbers
AND NOT EXISTS (
SELECT Employee, Sequence
FROM
(SELECT Employee, Sequence,
(
CASE WHEN (Client_Id = #Client_Id OR Client_Id IS NULL OR #Client_Id IS NULL) THEN 1 ELSE 0 END +
CASE WHEN (Project_ID = #Project_ID OR Project_ID IS NULL OR #Project_ID IS NULL) THEN 1 ELSE 0 END +
CASE WHEN (Phase = #Phase OR Phase IS NULL OR #Phase IS NULL) THEN 1 ELSE 0 END +
CASE WHEN (Task = #Task OR Task IS NULL OR #Task IS NULL) THEN 1 ELSE 0 END
) AS MatchCount
FROM myTable) mt2
WHERE mt2.MatchCount =
(
SELECT MAX(
CASE WHEN (Client_Id = #Client_Id OR Client_Id IS NULL OR #Client_Id IS NULL) THEN 1 ELSE 0 END +
CASE WHEN (Project_ID = #Project_ID OR Project_ID IS NULL OR #Project_ID IS NULL) THEN 1 ELSE 0 END +
CASE WHEN (Phase = #Phase OR Phase IS NULL OR #Phase IS NULL) THEN 1 ELSE 0 END +
CASE WHEN (Task = #Task OR Task IS NULL OR #Task IS NULL) THEN 1 ELSE 0 END
)
FROM myTable
)
AND mt2.Sequence = myTable.Sequence AND mt2.MatchCount > myTable.MatchCount
)
Note: This will return all records in the table when the number of matching fields is zero.
I'm sure they're are ways this could be cleaned up to not be so verbose by inserting all matching rows into a temp table and including the number of columns that match (MatchCount), there by reducing the query considerably.
Now, since you want unique Sequences and the highest matching row / rows to be returned the result you're looking for is more like this:
DECLARE #Client_Id VARCHAR(MAX) = '500'
DECLARE #Project_ID VARCHAR(MAX) = '3'
DECLARE #Phase VARCHAR(MAX) = NULL
DECLARE #Task VARCHAR(MAX) = NULL
INSERT INTO #myTempTable SELECT Employee, Sequence,
(
CASE WHEN (Client_Id = #Client_Id OR Client_Id IS NULL OR #Client_Id IS NULL) THEN 1 ELSE 0 END +
CASE WHEN (Project_ID = #Project_ID OR Project_ID IS NULL OR #Project_ID IS NULL) THEN 1 ELSE 0 END +
CASE WHEN (Phase = #Phase OR Phase IS NULL OR #Phase IS NULL) THEN 1 ELSE 0 END +
CASE WHEN (Task = #Task OR Task IS NULL OR #Task IS NULL) THEN 1 ELSE 0 END
) AS MatchCount,
(
CASE WHEN (Client_Id IS NULL) THEN 1 ELSE 0 END +
CASE WHEN (Project_ID IS NULL) THEN 1 ELSE 0 END +
CASE WHEN (Phase IS NULL) THEN 1 ELSE 0 END +
CASE WHEN (Task IS NULL) THEN 1 ELSE 0 END
) AS NullCount
-- ,(
-- CASE WHEN (Client_Id = #Client_Id OR #Client_Id IS NULL) THEN 1 ELSE 0 END +
-- CASE WHEN (Project_ID = #Project_ID OR #Project_ID IS NULL) THEN 1 ELSE 0 END +
-- CASE WHEN (Phase = #Phase OR #Phase IS NULL) THEN 1 ELSE 0 END +
-- CASE WHEN (Task = #Task OR #Task IS NULL) THEN 1 ELSE 0 END
-- ) AS MatchCountWithoutNulls
SELECT Employee, Sequence
FROM #myTempTable mtt
WHERE MatchCount = (
SELECT MAX(MatchCount)
FROM #myTempTable mtt2
WHERE mtt2.Sequence = mtt.Sequence
)
AND NullCount = (
SELECT MIN(NullCount)
FROM #myTempTable mtt2
WHERE mtt2.Sequence = mtt.Sequence
)
Or something very close to that, I don't have a test table made up atm so I can't kick it around and see.

Sql Server Where Case Then Is Null Else Is Not Null

I have a procedure which receive a bit variable called #FL_FINALIZADA.
If it is null or false I want to restrict my select to show only the rows that contain null DT_FINALIZACAO values. Otherwise I want to show the rows containing not null DT_FINALIZACAO values.
Something like this:
SELECT
*
FROM
MyTable
WHERE
...
AND
(
OPE.DT_FINALIZACAO = (
CASE
WHEN (#FL_FINALIZADA <> 1)
THEN NULL
END
) OR
OPE.DT_FINALIZACAO IS NOT NULL
)
In this case I receive the message:
None of the result expressions in a
CASE specification can be NULL.
How can I achieve this?
Thanks in advance.
SELECT
*
FROM
MyTable
WHERE
(ISNULL(#FL_FINALIZADA, 0) = 0
AND
OPE.DT_FINALIZACAO IS NULL
)
OR
(#FL_FINALIZADA = 1
AND
OPE.DT_FINALIZACAO IS NOT NULL
)
Change the AND to be:
AND (((#FL_FINALIZADA <> 1) AND (OPE.DT_FINALIZACAO IS NULL)) OR ( (#FL_FINALIZADA = 1) AND (OPE.DT_FINALIZACAO IS NOT NULL)))
If the bit flag is 1 then DT_FINALIZACAO can't be null.
IF #FL_FINALIZADA IS NULL
SET #FL_FINALIZADA = 0
SELECT * FROM NewsletterSubscribers
WHERE
(#FL_FINALIZADA = 0 AND OPE.DT_FINALIZACAO IS NULL)
OR
(#FL_FINALIZADA = 1 AND OPE.DT_FINALIZACAO IS NOT NULL)
My detailed SQL is a little rusty, but have you tried using 0 insted of NULL? I would expect 0 to evaluate the same as NULL in that select

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