Compare dates regardless of time(MSSQL) - sql

I Used this Store procedure to return data from special date . my QueueDate type is datetime , but when i want use = in Where Clause it return 0 , i want all field that are in one day independence in time of field.
ALTER PROCEDURE [dbo].[SP_GET_QUEUESINFO_BY_DATE]
AS
BEGIN
declare #date2 datetime
set #date2= '2012-09-21'
select COUNT(QueueID) ,
sum(case when QueueNumIn != 0 THEN 1 else 0 end) as 'InQueue',
sum(case when QueueNumOut != 0 THEN 1 else 0 end) as 'OutQueue'
from Queue where QueueDate >= #date2 -- QueueDate = #date2
END

You can CAST the column name to change the datatype from DATETIME to DATE (prior to version 2008+). Try,
ALTER PROCEDURE [dbo].[SP_GET_QUEUESINFO_BY_DATE]
AS
BEGIN
declare #date2 datetime
set #date2= '2012-09-21'
select COUNT(QueueID) ,
sum(case when QueueNumIn != 0 THEN 1 else 0 end) as 'InQueue',
sum(case when QueueNumOut != 0 THEN 1 else 0 end) as 'OutQueue'
from Queue
where CAST(QueueDate as DATE) >= #date2 -- QueueDate = #date2
END

SQL Server, correct?
To compare just the date component of a DateTime value and your are using SQL Server 2008 or higher, you can, as noted cast/convert to a Date datatype. Something like this should do you:
select *
from foo
where convert(date,foo.someDateTimeColumn) = '2012-10-27'
For any version of SQL Server the following will work:
select *
from foo
where convert(datetime,convert(varchar,foo.someDateTimeColumn,112),112) = '2012-10-27'
The above, using the 112 style, converts the datetime value to a compact form ISO 8601 date string 'yyyymmdd' and then converts that back to a datetime value.
Alternatively, for any version of SQL Server, you can test against a time period:
declare
#dtNow datetime
set #dtNow = current_timestamp
declare
#TodayStartOfDay datetime ,
#TodayEndOfDay datetime
set #TodayStartOfDay = convert(datetime,convert(varchar,#dtNow,112),112)
set #TodayEndOfDay = dateadd(ms,-3,datetime(day,1,#dtFrom))
...
select *
from foo
where foo.someDateTimeColumn between #TodayStartOfDay and #TodayEndOfDay
The advantage of this approach is that any indices on your DateTime column are eligible for use by the query optimizer.

WHERE DATEDIFF(DAY,#date2, QueueDate)=0

Related

Week difference like today's date and and 7 days before date

I want both ways whether I put the date in terms of -100 or a string date .So I use nvarchar because it accepts both integer as well as string values but it is not working please suggest me some solution.
The code is working fine in case of string date but in numeric it is creating problem
declare #date nvarchar(100);
declare #date1 nvarchar(100);
set #date = '2019-08-11'
set #date1= -100
select
(case isdate(#date)
when 1 then cast(#date as datetime)
when 0 then dateadd(day,cast(#date as int),getdate())
end)
as fromDate,
(case isdate(#date1)
when 1 then DATEADD(day, -7, convert(datetime,#date1,0))
when 0 then dateadd(day,cast(-7 as
int),convert(datetime,#date1,0))
end)
as toDate
I want the output of dates in such a manner it accepts both -100 or a string date
and return two dates like fromdate and todate but having 7 days gap.
You have made a small error in your 2nd column case. You use #date1 instead of getdate() when the input is a number.
Here is the fixed version
declare #date nvarchar(100);
declare #date1 nvarchar(100);
set #date = '2019-08-11'
set #date1= -100
select
(case isdate(#date)
when 1 then cast(#date as datetime)
when 0 then dateadd(day,cast(#date as int),getdate())
end) as fromDate,
(case isdate(#date1)
when 1 then DATEADD(day, -7,
convert(datetime,#date1,0))
when 0 then dateadd(day,-7 + cast(#date1 as int),getdate())
end) as toDate

How to avoid not to query tables or views in scalar functions?

I have scalar functions( 4 functions) in my View. It drastically reduces the view's performance. I believe the reason for that is I use SELECT queries in my scalar functions.
EG:
CREATE FUNCTION [dbo].[udf_BJs_GENERAL]
(
#TankSystemId int,
#TimeStamp datetime2(7)
)
RETURNS varchar(10)
AS
BEGIN
DECLARE #leakChk varchar(10);
DECLARE #allowableVariance float;
DECLARE #GallonsPumped int;
DECLARE #DailyOverOrShort float;
DECLARE #TimePeriod datetime2(7);
DECLARE #ReportDate datetime2(7)
SELECT TOP 1 #TimePeriod = Date
FROM [bjs].udv_DailySiraData
where TankSystemId=#TankSystemId ORDER BY Date DESC
SET #ReportDate=#TimePeriod
IF( #TimeStamp <= #TimePeriod)
SET #ReportDate=#TimeStamp
SELECT #GallonsPumped = SUM(GallonsPumped)
FROM [bjs].[udv_DailySiraData]
where TankSystemId=#TankSystemId
and Date <=#ReportDate and Date >= DATEADD(mm, DATEDIFF(mm,0,#ReportDate), 0)
SELECT #DailyOverOrShort = SUM(DailyVar)
FROM [bjs].[udv_DailySiraData]
where TankSystemId=#TankSystemId
and Date <=#ReportDate and Date >= DATEADD(mm, DATEDIFF(mm,0,#ReportDate), 0)
SELECT #allowableVariance= (#GallonsPumped/100) + 130
SET #leakChk='FAIL'
IF (#allowableVariance > ABS(#DailyOverOrShort))
SET #leakChk = 'PASS'
RETURN #leakChk;
How can i avoid such situations? Is there a way to do select queries in my View and pass that result to my scalar function?
Try this:
create function dbo.udf_BJs_GENERAL(
#TankSystemId int,
#TimeStamp datetime2(7)
) returns varchar(10) as
with dates as (
select top 1
ReportDate = case when #TimeStamp <= Date then #TimeStamp else Date
from bjs.udv_DailySiraData
where TankSystemId=#TankSystemId
order by Date desc
),
gallons as (
select
allowableVariance = ( sum(GallonsPumped)/100) + 130,
DailyOverOrShort = sum(DailyVar)
from bjs.udv_DailySiraData data
join dates
on data.Date <= dates.ReportDate
and date.Date >= dateadd(mm, datediffmm, 0, dates.ReportDate), 0)
where TankSystemId = #TankSystemId
)
select
leakChk = cast( case when allowableVariance > ABS(DailyOverOrShort))
then 'PASS' else 'FAIL' end as varchar(10) )
from gallons
your case is special, your have a special input parameter,assue the timestamp parameter is on Day level
This view will return check result of each TankSystemId on every day.
Then join will your query with TankSystemId and Day.
But if the input parameter is more detail. I think it is difficult to convert this function to view
CREATE view [dbo].[uvw_BJs_GENERAL]
AS
BEGIN
/*
SET #ReportDate=#TimePeriod
IF( #TimeStamp <= #TimePeriod)
SET #ReportDate=#TimeStamp
*/
SELECT TankSystemId,b.[Date]
,GallonsPumped = SUM(GallonsPumped),DailyOverOrShort = SUM(DailyVar)
,leakChk=CASE WHEN (SUM(GallonsPumped)/100) + 130)> ABS(SUM(DailyVar)) THEN 'PASS' ELSE 'FAIL' END
FROM [bjs].[udv_DailySiraData] AS a
INNER JOIN (
SELECT CONVERT(DATE,[Date]) AS [Date] FROM [bjs].[udv_DailySiraData] GROUP BY TankSystemId, CONVERT(DATE,[Date])
) b ON a.TankSystemId=b.TankSystemId AND DATEDIFF(d,a.[Date],b.[Date])>=0
-- and Date <=#ReportDate and Date >= DATEADD(mm, DATEDIFF(mm,0,#ReportDate), 0)
GROUP BY TankSystemId,b.[Date]
END

Counting records with a specific date value

I want to get all records entered with specific day, for example today:
ALTER PROCEDURE [dbo].[SP_GET_QUEUESINFO_BY_DATE]
#date nvarchar = '2012-09-21'
AS
BEGIN
declare #dateStart nvarchar(50) = #date + ' 00:00:00.0'
declare #dateEnd nvarchar(50) = #date + ' 23:59:59.437';
declare #returnData table (allQueue int,inQueue int,outQueue int)
SELECT 'table1' as table_name, COUNT(*)
FROM Queue as Counts
UNION ALL
SELECT 'table2' as table_name,COUNT(*) FROM Queue as Counts
WHERE QueueDate BETWEEN #dateStart AND #dateEnd
AND QueueNumIn != 0
END
Edited :
I Edited my code now it works :
ALTER PROCEDURE [dbo].[SP_GET_QUEUESINFO_BY_DATE]
AS
BEGIN
declare #date2 datetime
set #date2= '2012-09-21'
SELECT 'AllQueue' as table_name, COUNT(*)
FROM Queue as sdfds
UNION ALL
SELECT 'InQueue' as table_name,COUNT(*)
FROM Queue as sdfds
WHERE QueueDate >=#date2
AND QueueNumIn != 0
UNION ALL
SELECT 'OutQueue' as table_name, COUNT(*) FROM Queue as sdfds
WHERE QueueDate >=#date2
AND QueueNumOut != 0
END
It returns three records:
One problem is that the second column has no name. Why? Also, I want to return just one record that has three rows, not 3 separate records that have 2 fields.
you need to cast your varchar to datetime. and i think you want to assign Counts alias to Count(*)
ALTER PROCEDURE [dbo].[SP_GET_QUEUESINFO_BY_DATE]
#date nvarchar = '2012-09-21'
AS
BEGIN
declare #dateStart DATETIME = CAST(#date AS DATETIME)
declare #dateEnd DATETIME = DATEADD(hh,24,CAST(#date AS DATETIME))
declare #returnData table (allQueue int,inQueue int,outQueue int)
select 'table1' as table_name,COUNT(*) as Counts from QUEUE AS tb1
union all
select 'table2' as table_name,COUNT(*) as Counts from QUEUE AS tb2 where QueueDate >= #dateStart and QueueDate < #dateEnd and QueueNumIn !=0
END
not sure why returning all if you only want those in the spetial date.
Also, is better not to use between in Dates
ALTER PROCEDURE [dbo].[SP_GET_QUEUESINFO_BY_DATE]
#date datetime = '2012-09-21'
AS
BEGIN
select count(*) as 'AllQueue' ,
sum(case when QueueDate >=#date and QueueNumIn != 0 THEN 1 else 0 end) as 'InQueue',
sum(case when QueueDate >=#date and QueueNumOut != 0 THEN 1 else 0 end) as 'OutQueue'
from Queue
END
this should work.
this will give you something like
Allqueue inqueue, outqueue
----------------------------------------------------
11 | 8 | 10
This Code Worked and is edited code from ElVieejo
ALTER PROCEDURE [dbo].[SP_GET_QUEUESINFO_BY_DATE]
AS
BEGIN
declare #date2 datetime
set #date2= '2012-09-21'
select COUNT(QueueID) ,
sum(case when QueueNumIn != 0 THEN 1 else 0 end) as 'InQueue',
sum(case when QueueNumOut != 0 THEN 1 else 0 end) as 'OutQueue'
from Queue where QueueDate >= #date2
END

SQL Server query buildup

I have a set with data in a SQL Server database and I need to calculate uptime of a machine. I'm using two variables to determine uptime or downtime. These two variables are machine_ON and failure(s). machine_ON is only one variable in the database, failure can be 64 different failures, but all indicates as fx_x.
The status information of these variables is stored in the database as follow:
timestamp failurebitNr timestampOutOfAlarm
2012-01-17 10:38:58.000 f1_14 2012-01-17 10:39:05.000
Meaning: failure f1_14 was active from 2012-01-17 10:38:58.000 until 2012-01-17 10:39:05.000
Also the machine_ON state is saved in the same table on the same way, only the failurebitNr has a different value [t2_13].
So to determine the uptime, I need to get the timediff between timestamp and timestampOutOfAlarm where failurebutNr = 't2_13' minus any failure time.
So for example I have those rows in my database:
This should give the following graphical representation:
Green is uptime, red is downtime.
I'm used to work with PHP and than use a while loop and file some array's and do other scripting. But now I need to do this all in a SQL Server database in query ways...
So, how can I calculate the uptime (green) and downtime (red)?
UPDATE
I've tried to get the time in seconds that the machine is ON. I used this query:
<!-- language: lang-sql -->
DECLARE #startDate datetime
DECLARE #endDate datetime
DECLARE #projectNr int
DECLARE #MachineNr nvarchar(10)
SET #startDate = '2012-01-01 00:00:00.000'
SET #endDate = '2012-02-01 00:00:00.000'
SET #projectNr = '1234567'
SET #MachineNr = '2'
SELECT
DATEDIFF("SECOND",
CASE WHEN timestamp < #startDate
THEN #startDate
ELSE timestamp
END,
CASE WHEN timestampOutOfAlarm > #endDate OR timestampOutOfAlarm IS NULL
THEN #endDate
ELSE timestampOutOfAlarm
END) AS Uptime
FROM
[table]
WHERE
timestamp < #endDate
AND (timestampOutOfAlarm > #startDate OR timestampOutOfAlarm IS NULL)
AND fileProjectNr = #projectNr
AND fileProjectMachineNr = #MachineNr
AND (failureBitNr = 't2_13' AND failureBitValue = '1')
Problem solved:
I did it in 2 stored procedures, or Query's. One for getting the "ON" time and one for getting all the "DOWN" time within the "ON" time. Whith those two times I can calculate the uptime, downtime, maintenance time.
Query for ON time:
<!-- language: lang-sql -->
SELECT fctAlarmId,
fileProjectNr,
fileProjectMachineNr,
failureBitNr,
timestamp,
CASE WHEN timestampOutOfAlarm > #endDate OR timestampOutOfAlarm IS NULL
THEN #endDate
ELSE timestampOutOfAlarm
END
AS timestampOutOfAlarm
INTO #tempTable1
FROM fctAlarmHistory
WHERE (timestampOutOfAlarm >= #startDate OR timestampOutOfAlarm = NULL)
AND timestamp < #endDate
AND failureBitValue = 1
AND failureBitNr = 't2_13'
AND fileProjectNr = #projectNr
And fileProjectMachineNr = #ProjectMachineNr
-- SUM the result of all ON times into OnTime in seconds
SELECT
SUM(DATEDIFF("SECOND",
CASE WHEN timestamp < #startDate
THEN #startDate
ELSE timestamp
END,
CASE WHEN timestampOutOfAlarm > #endDate
THEN #endDate
ELSE timestampOutOfAlarm
END)) AS OnTime
FROM
#tempTable1
Query for Downtime during ON time:
<!-- language: lang-sql -->
SELECT fctAlarmId,
fileProjectNr,
fileProjectMachineNr,
failureBitNr,
timestamp,
CASE WHEN timestampOutOfAlarm > #endDate OR timestampOutOfAlarm IS NULL
THEN #endDate
ELSE timestampOutOfAlarm
END
AS timestampOutOfAlarm
INTO #tempTable1
FROM fctAlarmHistory
WHERE (timestampOutOfAlarm >= #startDate OR timestampOutOfAlarm = NULL)
AND timestamp < #endDate
AND failureBitValue = 1
AND failureBitNr = 't2_13'
AND fileProjectNr = #projectNr
And fileProjectMachineNr = #ProjectMachineNr
SELECT fctAlarmId,
fileProjectNr,
fileProjectMachineNr,
failureBitNr,
timestamp,
CASE WHEN timestampOutOfAlarm > #endDate OR timestampOutOfAlarm IS NULL
THEN #endDate
ELSE timestampOutOfAlarm
END
AS timestampOutOfAlarm
INTO #tempTable2
FROM fctAlarmHistory
WHERE (timestamp BETWEEN #startDate AND #endDate)
AND failureBitValue = 1
AND (failureBitNr LIKE'f%')
AND fileProjectNr = #projectNr
And fileProjectMachineNr = #ProjectMachineNr
CREATE TABLE #tempTable3
(
ID int IDENTITY(1,1),
timestamp datetime,
timestampOutOfAlarm datetime
)
DECLARE failure_Cursor CURSOR FOR
SELECT timestamp, timestampOutOfAlarm
FROM #tempTable2
ORDER BY timestamp ASC
OPEN failure_Cursor
-- Perform the first fetch.
FETCH NEXT FROM failure_Cursor
INTO #rij_timestamp, #rij_timestampOutOfAlarm
INSERT INTO #tempTable3 (timestamp, timestampOutOfAlarm) VALUES(#rij_timestamp,#rij_timestampOutOfAlarm)
-- Check ##FETCH_STATUS to see if there are any more rows to fetch.
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT #rij_timestamp
IF #rij_timestamp <= (SELECT TOP 1 timestampOutOfAlarm FROM #tempTable3 ORDER BY timestamp DESC)
BEGIN
IF #rij_timestampOutOfAlarm > (SELECT TOP 1 timestampOutOfAlarm FROM #tempTable3 ORDER BY timestamp DESC)
BEGIN
UPDATE #tempTable3 SET timestampOutOfAlarm = #rij_timestampOutOfAlarm WHERE ID = (SELECT TOP 1 ID FROM #tempTable3 ORDER BY timestamp DESC)
END
END
ELSE
INSERT INTO #tempTable3 (timestamp, timestampOutOfAlarm) VALUES(#rij_timestamp,#rij_timestampOutOfAlarm)
FETCH NEXT FROM failure_Cursor
INTO #rij_timestamp, #rij_timestampOutOfAlarm
END
CLOSE failure_Cursor
DEALLOCATE failure_Cursor
-- Select the failure time.
SELECT
SUM(DATEDIFF("SECOND",
CASE WHEN tt3.timestamp < #startDate
THEN #startDate
ELSE tt3.timestamp
END,
CASE WHEN tt3.timestampOutOfAlarm > tt1.timestampOutOfAlarm
THEN tt1.timestampOutOfAlarm
ELSE tt3.timestampOutOfAlarm
END)) AS DownTime
FROM
#tempTable3 tt3
INNER JOIN
#tempTable1 tt1
ON
tt3.timestamp BETWEEN tt1.timestamp AND tt1.timestampOutOfAlarm

Best way to compare dates without time in SQL Server

select * from sampleTable
where CONVERT(VARCHAR(20),DateCreated,101)
= CONVERT(VARCHAR(20),CAST('Feb 15 2012 7:00:00:000PM' AS DATETIME),101)
I want to compare date without time
Is above query is ok? or other better solution you suggest
I am using SQL Server 2005
Date saved in UTC format on server
Users against this data belongs different timezone
Simple Cast to Date will resolve the problem.
DECLARE #Date datetime = '04/01/2016 12:01:31'
DECLARE #Date2 datetime = '04/01/2016'
SELECT CAST(#Date as date)
SELECT CASE When (CAST(#Date as date) = CAST(#Date2 as date)) Then 1 Else 0 End
Don't use convert - that involves strings for no reason. A trick is that a datetime is actually a numeric, and the days is the integer part (time is the decimal fraction); hence the day is the FLOOR of the value: this is then just math, not strings - much faster
declare #when datetime = GETUTCDATE()
select #when -- date + time
declare #day datetime = CAST(FLOOR(CAST(#when as float)) as datetime)
select #day -- date only
In your case, no need to convert back to datetime; and using a range allows the most efficent comparisons (especially if indexed):
declare #when datetime = 'Feb 15 2012 7:00:00:000PM'
declare #min datetime = FLOOR(CAST(#when as float))
declare #max datetime = DATEADD(day, 1, #min)
select * from sampleTable where DateCreated >= #min and DateCreated < #max
SELECT .......
FROM ........
WHERE
CAST(#DATETIMEVALUE1 as DATE) = CAST(#DATETIMEVALUE2 as DATE)
The disadvantage is that you are casting the filter column.
If there is an index on the filter column, then, since you are casting, the SQL engine can no longer use indexes to filter the date more efficiently.
Description
Don't convert your Date to a varchar and compare because string comparisson is not fast.
It is much faster if you use >= and < to filter your DateCreated column.
If you have no parameter (like in your sample, a string) you should use the ISO Format <Year><Month><Day>.
Sample
According to your sample
DECLARE #startDate DateTime
DECLARE #endDate DateTime
SET #startDate = '20120215'
SET #endDate = DATEADD(d,1,#startDate)
SELECT * FROM sampleTable
WHERE DateCreated >= #startDate AND DateCreated < #endDate
More Information
MSDN - DATEADD (Transact-SQL)
Use 112 CONVERT's format
select *
from sampleTable
where
CONVERT(VARCHAR(20),DateCreated,112)
= CONVERT(VARCHAR(20),CAST('Feb 15 2012 7:00:00:000PM' AS DATETIME),112)
or
if your sql server version 2008+ use DATE type
select * from sampleTable
where CONVERT(DATE,DateCreated)
= CONVERT(DATE,CAST('Feb 15 2012 7:00:00:000PM' AS DATETIME))
declare #DateToday Date= '2019-10-1';
print #DateToday;
print Abs(datediff(day, #DateToday,CAST('oct 1 2019 7:00:00:000PM' AS DATETIME))) < 3
this is compare whin 3 days.
i test this on SQL Server 2014, it works.
select * from sampleTable
where date_created ='20120215'
This will also compare your column with the particular date
without taking time into account