T-SQL IF Block Not Executing Though Conditions Are Met - sql-server-2008

I've got the following SQL statement that I am working on. I've trimmed it down to the parts necessary to illustrate the problem.
DECLARE #mwareId as int = 9647,
#startDate as datetime = '2011-07-20',
#endDate as datetime = '2011-07-20'
IF OBJECT_ID('tempdb..#tmpInvoiceList', 'U') IS NOT NULL DROP TABLE #tmpInvoiceList
-- Get base invoice list for customer
SELECT invoiceId
,invoiceNumber
,customerId
,customerName
,customerCode
,createDate
,lastModifiedDate
,invoiceDate
,totalInvoiceAmount
,statusId
,isPaid
INTO #tmpInvoiceList
FROM Invoice.Invoice
-- Apply date range if applicable
IF ( #startDate != NULL AND #endDate != NULL )
BEGIN
DELETE FROM #tmpInvoiceList
WHERE invoiceDate NOT BETWEEN #startDate AND #endDate
END
SELECT * FROM #tmpInvoiceList
I have the #startDate and #endDate variables set to date values. The problem is that the if block that applies the date range to the temp table is not executing, though neither of the two variables are null, and I can't find a reason for this.

As far as I'm aware, TSQL doesn't support the != operator for null checks. Try this:
IF ( #startDate IS NOT NULL AND #endDate IS NOT NULL )

IS [NOT] NULL is the right way to compare value with NULL. All of (NULL != NULL) , (1!= NULL), (NULL =NULL) evaluate as NULL(false)

You have to use IS NOT NULL instead of != NULL
IF ( #startDate IS NOT NULL AND #endDate IS NOT NULL )
...

Related

Searching - Stored Procedure - DateTime variable - Easy Resolution?

I am trying to create a stored procedure that when entered the three variables:
#Bank_Number = 530
#Branch_Number = 002
#Date_From = 10/28/2014
#Date_To = 10/29/2014
It will return all records between the Date_From and Date_To dates that match the Bank_Number and Branch_Number.
The code I have here is incorrect slightly I'm not sure how to proceed.
ALTER PROCEDURE [dbo].[Something_Proc]
#Bank_Number varchar(3),
#Branch_Number varchar(3),
#Date_From datetime,
#Date_To datetime
AS
BEGIN
SET NOCOUNT ON;
DECLARE #bankNumber varchar(3) = #Bank_Number,
#branchNumber varchar(3) = #Branch_Number,
#dateCreated datetime = #Date_From,
#dateCreated datetime = #Date_To
SELECT DISTINCT
A.bankNumber,
A.branchNumber,
CONVERT(VARCHAR(8), A.dateCreated, 1)
FROM
dbo.(table from picture) A
WHERE
(#bankNumber IS NULL OR Bank_Number LIKE #bankNumber + '%')
AND (#branchNumber IS NULL OR Branch_Number LIKE #branchNumber + '%')
AND (#dateCreated IS NULL OR (MONTH(dateCreated) = MONTH(#dateCreated)
AND DAY(dateCreated) = DAY(#dateCreated)
AND YEAR(dateCreated) = YEAR(#dateCreated)))
END
Can't you just use something like this?
WHERE
(#bankNumber IS NULL OR Bank_Number LIKE #bankNumber + '%')
AND (#branchNumber IS NULL OR Branch_Number LIKE #branchNumber + '%')
AND (#Date_From IS NULL OR #Date_From <= DateCreated)
AND (#Date_To IS NULL OR DateCreated <= #DateTo)
Basically, either your #Date_From and #Date_To parameters are NULL (then that parameters isn't used in any way), or if it's not null, then it's used to compare DateCreated to be equal or larger than #Date_From, and equal or smaller than #Date_To ....

How to use BETWEEN for datetime stored procedure

I am creating a stored procedure for searching. DateOrdered is column name in table of datetime type.
The problem is that I want to perform search on this column. The user can search on start date and end date. Also user can send null for any parameter, like start date or end date.
When the user will not send the start date or end date, I shall search on another option. My problem is that how can I handle this below is the query I tried, but without success
SELECT
#C_Order_ID = C_Order_ID
FROM
C_Order COrder
WHERE
(#AD_Org_ID IS NULL OR
COrder.AD_Org_ID IN (SELECT ID FROM fnSplitter(#AD_Org_ID)))
AND (#AD_Client_ID IS NULL OR
#AD_Client_ID IN (SELECT ID FROM fnSplitter(#AD_Client_ID)))
AND (#IsActive IS NULL OR COrder.IsActive = #IsActive)
AND (#startDate IS NULL OR
COrder.DateOrdered = #startDate BETWEEN #EndDate IS NULL
OR COrder.DateOrdered = #EndDate)
Thanks for your reply .
You may try like this:
COrder.DateOrdered BETWEEN #startDate AND #EndDate
So your query would be like
SELECT #C_Order_ID= C_Order_ID FROM C_Order COrder
WHERE
(#AD_Org_ID IS NULL OR COrder.AD_Org_ID IN (Select ID From fnSplitter(#AD_Org_ID)))
AND (#AD_Client_ID IS NULL OR #AD_Client_ID IN (Select ID From fnSplitter(#AD_Client_ID)))
AND (#IsActive IS NULL OR COrder.IsActive = #IsActive)
AND (#startDate IS NULL OR COrder.DateOrdered BETWEEN isnull(#startDate,'') AND isnull(#EndDate,''))
or better
SELECT #C_Order_ID= C_Order_ID FROM C_Order COrder
WHERE
(#AD_Org_ID IS NULL OR COrder.AD_Org_ID IN (Select ID From fnSplitter(#AD_Org_ID)))
AND (#AD_Client_ID IS NULL OR #AD_Client_ID IN (Select ID From fnSplitter(#AD_Client_ID)))
AND (#IsActive IS NULL OR COrder.IsActive = #IsActive)
AND (CAST(#startDate AS DATE) IS NULL OR (CAST(#startDate AS DATE) IS NULL OR CAST(COrder.DateOrdered AS DATE) >=CAST(#startDate AS DATE))
AND (CAST(#endDate AS DATE) IS NULL OR CAST(COrder.DateOrdered AS DATE) <=CAST(#endDate AS DATE))
SELECT #C_Order_ID= C_Order_ID FROM C_Order COrder
WHERE
(#AD_Org_ID IS NULL OR COrder.AD_Org_ID IN (Select ID From fnSplitter(#AD_Org_ID)))
AND (#AD_Client_ID IS NULL OR #AD_Client_ID IN (Select ID From fnSplitter(#AD_Client_ID)))
AND (#IsActive IS NULL OR COrder.IsActive = #IsActive)
AND (#startDate IS NULL OR COrder.DateOrdered BETWEEN #startDate AND #EndDate
OR COrder.DateOrdered = #EndDate)
Aaron Bertrand has written a good article about using BETWEEN with date ranges - What do BETWEEN and the devil have in common?, this is worth a read. Also it looks like you are passing a comma separated list in a string, then splitting it with a function fnsplitter, you may want to consider using table-valued paramters
However, to actually answer your question you can use the above idea of not using between and change your query to:
AND (#startDate IS NULL OR COrder.DateOrdered >= #startDate)
AND (#EndDate IS NULL OR COrder.DateOrdered <= #EndDate)
So you have 4 permutations.
Both #StartDate and #EndDate are null - returns all dates
#StartDate is not null and #EndDate is null - returns all dates after #StartDate
#StartDate is null and #EndDate is not null - returns all dates before #EndDate
Both #StartDate and #EndDate are not null - returns all dates between #StartDate and #EndDate
Based on your comments on another answer, it sounds like you may be passing a date as the #EndDate parameter, e.g. 2014-08-28, but still want to include all records on that date, even if they have a time associated, e.g. 2014-08-28 12:00, this is exactly why BETWEEN is not used for date ranges, instead you need to use the less than operator and add 1 day to your End date:
AND (#startDate IS NULL OR COrder.DateOrdered >= #startDate)
AND (#EndDate IS NULL OR COrder.DateOrdered < DATEADD(DAY, 1, #EndDate))

SSRS String -vs- Data Integer

I am working on a SSRS report and using a parameter that allows you to choose multiple options. However, when I do this I get an error that states:
Error Converting Data Type nVarChar to Int.
The data in the database is an Integer. The parameter is set up as an Integer and it works great when only choosing one option. The issue comes when I choose multiple options.
My co-worker came up with one work-around but I would like something a little more elegant and easier to plug in if possible.
Here is his work-around:
ALTER PROCEDURE [dbo].[DtaPrep_MktgClients]
#BegDate date = NULL
, #EndDate date = NULL
, #Species varchar(50) = 'canine,feline,K9,'
 , #HospList varchar(500) = NULL
This is where the hospmastid string gets converted into a temp table
/*
--===================================--
HOSPITALS SETUP
--===================================--
*/
If #HospList IS NOT NULL
BEGIN
DECLARE #WorkHospList varchar(500)
SET #WorkHospList = #HospList
;
CREATE TABLE #HospList
( HospID smallint NULL )
SET #CommaLoc = charindex(',', #WorkHospList)
WHILE #CommaLoc > 1
BEGIN
SET #curVal = LEFT(#WorkHospList, #commaloc-1 )
INSERT INTO
#HospList( HospID )
SELECT #curVal
SET #WorkHospList = substring( #WorkHospList, #commaloc+1, len(#WorkHospList) )
SET #CommaLoc = charindex(',', #WorkHospList)
END
END
This is using the temp table to accomplish the same thing as a “WHERE Hospmastid IN (101,102,103)…”
Method 1
SELECT
HospitalMasterID
, ClientID
, FirstName
, LastName
FROM
Client
WHERE
HospitalMasterID IN (Select HospID From #HospList )
Needless to say, I am sure there is a better way to accomplish this. If anyone has any ideas, please let me know.
Here is the full Query I am now using. But it is not selecting anything so there is an issue with the Created Table.
USE [xxxxx]
GO
/****** Object: StoredProcedure [dbo].[PriceErosion] Script Date: 11/26/2013 8:26:33 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
/*
-- =============================================
-- Author:
-- Create date: 11/25/2013
-- Description: Determines the products in which the price was lowered and revenue lost during a set time period.
-- =============================================
*/
--#StartDate as Date = Null
--,#EndDate as Date = Null
--,#CurDate as Date = Null
--,#Hospital as VarChar = Null
--,#Division as Int = Null
Declare #StartDate as Date = Null
Declare #EndDate as Date = Null
Declare #Hospital as Int = Null
Declare #Division as Int = Null
DECLARE #curDate Date = Null
SET #curDate = GETDATE()
Set #StartDate = CASE WHEN #StartDate IS NULL THEN DATEADD(dd, -31, Dateadd(dd, -1, #curdate) ) ELSE #StartDate END
Set #EndDate = CASE WHEN #EndDate IS NULL THEN Dateadd(dd, -1, #curdate) ELSE #EndDate END
Set #Hospital = Case When #Hospital IS Null Then '3' Else #Hospital End;
IF OBJECT_ID('tempdb.dbo.#HospList') IS NOT NULL DROP TABLE #HospList ;
If #Hospital IS NOT NULL
BEGIN
DECLARE #WorkHospList varchar(500)
Declare #CommaLoc as Int
Declare #curVal as int
SET #WorkHospList = #Hospital
;
CREATE TABLE #HospList
( HospID smallint NULL )
SET #CommaLoc = charindex(',', #WorkHospList)
WHILE #CommaLoc > 1
BEGIN
SET #curVal = LEFT(#WorkHospList, #commaloc-1 )
INSERT INTO
#HospList( HospID )
SELECT #curVal
SET #WorkHospList = substring( #WorkHospList, #commaloc+1, len(#WorkHospList) )
SET #CommaLoc = charindex(',', #WorkHospList)
END
END
Begin
-- Sets the Baseline Price Date in the PriceChangeHistory Table.
With PC1
as
(Select
HospitalMasterID
,TxnCode
,UserInfoMasterID
,Active
,min(TxnDateTime) as StartingDate
From
PriceChangeHistory
Where
TxnDateTime Between #StartDate and #EndDate
Group By
HospitalMasterID, TxnCode, UserInfoMasterID, Active)
-- Gets the Baseline Price for the period from the PriceChangeHistory Table
,PC
as
(Select
PC1.HospitalMasterID
,PC1.TxnCode
,PC1.UserInfoMasterID
,PC1.Active
,Cast (PC1.StartingDate as Date) as StartingDate
,PC2.OldPrice as StartingPrice
,PC2.NewPrice
,PC2.TxnSubType
From
PC1
Inner Join
PriceChangeHistory as PC2
On
PC1.HospitalMasterID = PC2.HospitalMasterID
and
PC1.TxnCode = PC2.TxnCode
and
PC1.StartingDate = PC2.TxnDateTime
Where
PC2.OldPrice > PC2.NewPrice)
--MedicalHistory Information
,MH
as
(Select
HospitalMasterID
,PatientID
,TxnDate
,TxnCode
,Description
,ListAmount
,ExtendedAmount
,TxnType
,Quantity
,(Case
When Quantity <> '1' Then (ListAmount/Quantity)
Else ListAmount
End) as UnitPrice
From
MedicalHistory
Where
TxnDate Between #StartDate and #EndDate
and
_IsServOrITem = 1)
-- Determines the Revenue lost per each sale, also reduces the results to only those items where the Price was lowered not raised.
,RL
as
(Select
PC.HospitalMasterID
,MH.PatientID
,PC.TxnCode
,PC.TxnSubType
,MH.Description
,PC.UserInfoMasterID as ChangedByUserID
,MH.TxnDate
,PC.StartingPrice
,Cast (MH.UnitPrice as Money) as UnitPrice
,Cast ((StartingPrice - UnitPrice) as Money) as RevenueLost
From
PC
Left OUter Join
MH
on
PC.HospitalMasterID = MH.HospitalMasterID
and
PC.TxnCode = MH.TxnCode
Where
PC.StartingPrice > MH.UnitPrice)
--- Determine the name of the tech changing the prices.
,UI
as
(Select
HospitalMasterID
,UserInfoMasterID
,Name
From
UserInfo)
--- Get the Division and Hospital Name for each Hospital.
,HODI
as
(Select
DI.DivisionID
,DI.DivisionName
,HO.HospMastID
,HO.HospCode
,HO.HospName
From
ref_Hospital as HO
inner Join
ref_Division as DI
on
HO.DivisionID = DI.DivisionID)
,HI
as
(Select
HODI.DivisionID
,HODI.DivisionName
,RL.HospitalMasterID
,HODI.HospCode
,HODI.HospName
,RL.PatientID
,RL.TxnCode
,RL.TxnSubType
,RL.Description
,RL.ChangedByUserID
,RL.TxnDate
,RL.StartingPrice
,RL.UnitPrice
,RL.RevenueLost
From
RL
Left Outer Join
HODI
ON
RL.HospitalMasterID = HODI.HospMastID
Where
TXNDate Between #StartDate and #EndDate)
Select
*
From
HI
Where
HospitalMasterID in (Select HospID from #Hosplist)
Order By
HOspitalMasterID
end
Prior to SQL Server 2008, the standard way to filter by one or more values was to pass an XML document to the Stored Procedure and join on it. In this case, you could pass the data as a string with the integers separated by commas, then convert that into an XML document, then join on the XML. So you should change the multiselect in SSRS to a text datatype. Here's a post that shows you how to open an XML document: http://blog.sqlauthority.com/2009/02/13/sql-server-simple-example-of-reading-xml-file-using-t-sql/
SQL Server 2008 lets you use table-valued parameters, but again, it might be best to pass the data as a string of comma separated integers and then let the stored procedure put the data into a table-valued parameter, and then join on that. Here's a post that describes how to use table valued parameters: http://blog.sqlauthority.com/2008/08/31/sql-server-table-valued-parameters-in-sql-server-2008/

check date between two dates or NULL in sql

I want to check date in between two dates or can pass as a NULL
using stored proc
code
declare #fromDate date = null
declare #toDate date = null
select * from Mytable
where date betweeen #fromDate and #toDate OR NULL (how to check for both parameters)
I have other 2 more parameters so irrespective with date result should be displayed.
if #todate and #fromDate is NULL
please help.
Try with coalesce function as below
declare #fromDate date = null
declare #toDate date = null
select * from Mytable
where date between coalesce(#fromDate,date) and coalesce(#toDate,date)
Pretty much convert your English to SQL:
where (date is null or date betweeen #fromDate and #toDate)
When searching for a better solution than "between" with "coalesce" i found this thread:
firebird SQL
param is never NULL
createdatum is never NULL
offdatum can be NULL - for obvious reasons ;)
Initial solution:
where
X = :X
AND
cast(:QryDateTime as DATE) between
createdatum and coalesce(offdatum, cast(:QryDateTime as DATE))
problem there was a little tricky: when using "now" as value for QryDateTime there was (very rarely) no result found - even if there should exist one
Problem was that now is evaluated every time separately and obviously not in the left-to-right order.
I finally changed it to:
where
X = :X
AND
iif(offdatum is null, 1, iif(offdatum > cast(:QryDateTime as DATE), 1, 0)) = 1
AND
cast(:QryDateTime as DATE) > createdatum

IF ELSE with NULL values mysql

im having problems creating a function that must return the amount of goals of a team as a home and away
First it sums all local goals, and then it sums all visitor goals, and saves into variables, but the problem is, i want to know what can i do if there is NO data, i mean, what can i do when it returns NULL, i tried with IF ELSE but still not working, here is the code:
CREATE DEFINER=`root`#`localhost` FUNCTION `vgoles`(`veq` int) RETURNS int(11)
BEGIN
#Routine body goes here...
DECLARE vgloc INT;
DECLARE vgvis INT;
DECLARE vgoles INT;
SELECT SUM(gloc) INTO #vgloc FROM partidos WHERE eqloc=#veq;
SELECT SUM(gvis) INTO #vgvis FROM partidos WHERE eqvis=#veq;
IF #vgloc = NULL THEN
SET #vgloc = 0;
END IF;
IF #vgvis = NULL THEN
SET #vgvis = 0;
END IF;
SET #vgoles=#vgloc+#vgvis;
RETURN #vgoles;
END
Thanks and have a nice day
The IF #vgloc = NULL THEN does not work as you expect because you can't check NULL with equality (=). NULL is a special value that is not equal to anything, not even to itself.
SELECT (3 = NULL) --yields--> NULL
SELECT NOT (3 = NULL) --yields--> NULL
SELECT (NULL = NULL) --yields--> NULL
SELECT (NULL <> NULL) --yields--> NULL
SELECT (NULL IS NULL) --yields--> TRUE
To check for NULL value, you need: IF #vgloc IS NULL THEN.
But you can also use COALESCE() function for further simplicity:
SELECT COALESCE(SUM(gloc),0) INTO #vgloc FROM partidos WHERE eqloc=#veq;
SELECT COALESCE(SUM(gvis),0) INTO #vgvis FROM partidos WHERE eqvis=#veq;