I have a query that monitors connection process. Now I'm stuck and need to set a proper monitoring for weekday and time range.
The process starts on Sunday 22:00, and goes down for 5 min. at 21:55 - every day to Friday. (not goes up from Friday 21:55 till 22:00 on Sunday)
Below is the SQL Query I tried:
IF CASE
WHEN (100 * DATEPART(hh, GETDATE()))
+ DATEPART(MINUTE, GETDATE())
BETWEEN 2155 AND 2200 -- Monitoring for whole day, wen connection is up
AND DATEPART(dw,GETDATE()), (100 * DATEPART(hh, GETDATE()))
+ DATEPART(MINUTE, GETDATE())
NOT BETWEEN (5, 2155) AND (0, 2200) --except trough Friday night to Sunday (weekdays and time).
THEN 1 ELSE 0 END = 0
You needed to add some SELECT statements into the parts of the case where you were getting the values to range between. Try this:
SELECT
CASE
WHEN(100 * DATEPART(hh, GETDATE())) + DATEPART(MINUTE, GETDATE()) -- = 731
BETWEEN 2155 AND 2200 -- Monitoring for whole day, wen connection is up
AND (
(
SELECT
DATEPART(dw, GETDATE())
) NOT BETWEEN(5) AND(0)
AND
(
SELECT
(100 * DATEPART(hh, GETDATE())) + DATEPART(MINUTE, GETDATE())
) NOT BETWEEN(2155) AND(2200)
)
THEN 1
ELSE 0
END;
The first calculation equals 731 so looking at the query I would except it to return '0' which it does
Related
AND (
(datediff(DAY,getdate(), '2020-07-14 00:00:00.000') = 5)
OR (
datediff(DAY,getdate(), A.HX_RELIEVING_DT) BETWEEN 0 AND 4
AND '2020-04-17 20:36:53.000' >= GETDATE()-1
)
)
This is the output I want for relieving date and last updated time but I am unable to get this
EMPLID LOCATION SUPERVISOR_ID HX_RELIEVING_DT LASTUPDDTTM
-- SINGAPORE --- 2020-07-14 00:00:00.000 2020-04-17 20:36:53.000
I believe you tried to write if #MyDate is past:
AND ((DATEDIFF(DAY, #MyDate, GETDATE()) = 5) OR (DATEDIFF( DAY, A.HX_RELIEVING_DT, GETDATE()) BETWEEN 0 AND 4 AND DATEADD(DAY, -1, GETDATE()) <= #MyDate))
If #MyDate is future:
AND ((DATEDIFF(DAY, GETDATE(), #MyDate) = 5) OR (DATEDIFF(DAY, GETDATE(), A.HX_RELIEVING_DT) BETWEEN 0 AND 4 AND DATEADD(DAY, 1, GETDATE()) <= #MyDate))
Last condition from your WHERE clause is basically filtering your record from the output.
AND '2020-04-17 20:36:53.000' >= GETDATE()-1
A date from month "April" can not be bigger than a date value from July, right? You can check the values you are using in different condition in WHERE clause with this below query. You will get your issue automatically.
SELECT *,
datediff(DAY,getdate(), '2020-07-14 00:00:00.000'),
datediff(DAY,getdate(), A.HX_RELIEVING_DT),
GETDATE()-1
FROM your_table A
I have a string value as 07052018080504623
It represents MM DD YYYY HH MM SS MS
means
MM = 07, DD = 05, YYYY=2018, HH = 08, MM=05 , SS= 04, MS = 623
Now I have a table defined as
declare #t table (WorkRequestId varchar(100))
insert into #t values
('07052018080504623'),('07062018012756663'),('07062018020148130'),('07062018095201231'),
('07062018102203805'),('07062018103718059'),('07062018110304836'),('07062018115356135'),
('07062018120624983'),('07062018124035480'),('07062018080504623'),('07062018070504623')
select
*
from #t
The records should be sorted in ascending order such that
WorkRequestId
07052018080504623
07062018095201231
07062018102203805
07062018103718059
07062018110304836
07062018115356135
07062018120624983
07062018124035480
07062018012756663
07062018020148130
The cutoff time is 8PM of previous day to 19:59:59 PM of next day.
In our example, 05 is previous day while 06 is next day.
Also no transaction happens between 1AM - 7:59:59 AM of next day. It starts again from 8AM of next day and continues till
19:59:59 PM.
So when we encounter 07062018012756663, the DD=06 and HH = 01. It means 13HRs (i.e. 1PM) of 6th. Same for 07062018020148130 where DD=06 and HH = 02 (i.e. 2PM or 14Hrs).
But 07062018095201231 where DD=06 and HH = 09 means 9AM of 6th.
That is why
07062018095201231 comes before 07062018012756663 and 07062018020148130
while ordering
My attempt so far (not correct yet)
select
*
,DY=SUBSTRING([WorkRequestId],3,2)
,HH = SUBSTRING([WorkRequestId],9,2)
,CurrentDY=CONVERT(varchar(2), getdate(), 103)
from #t
order by left([WorkRequestId],8) +
cast(iif(
SUBSTRING([WorkRequestId],3,2) = '6',--CONVERT(varchar(2), getdate(), 103),
iif(cast(SUBSTRING([WorkRequestId],9,2) as int) between 1 and 7,
cast(SUBSTRING([WorkRequestId],9,2) as int)+12,SUBSTRING([WorkRequestId],9,2)),
cast(SUBSTRING([WorkRequestId],9,2)as varchar(4)))as varchar(20))
+right([WorkRequestId],7)
So, I guess you should realize by now that storing dates as strings (and in fact, storing anything in the wrong data type) is bad practice.
The correct solution is to change the database structure to hold that data as DateTime2 instead of a string. However, assuming this can't be done for some reason, you can get the results you want by converting the string values to datetime2, adding 12 hours where the hour is between 1 a.m. and 8 a.m., and sort by that date.
I've written my suggestion in a cumbersome way because I wanted to show every part of the process - I've used 3 common table expression though if can be done in a single query - again, that's just to illustrate every step of the solution:
;WITH CTEDateParts AS -- break down the string to it's parts
(
SELECT WorkRequestId,
SUBSTRING(WorkRequestId, 5, 4) As Year,
SUBSTRING(WorkRequestId, 1, 2) As Month,
SUBSTRING(WorkRequestId, 3, 2) As Day,
SUBSTRING(WorkRequestId, 9, 2) As Hour,
SUBSTRING(WorkRequestId, 11, 2) As Minute,
SUBSTRING(WorkRequestId, 13, 2) As Second,
SUBSTRING(WorkRequestId, 15, 3) As Millisecond
FROM #t
), CTEDates AS -- create datetime values from the string parts
(
SELECT WorkRequestId,
CAST(Year +'-'+ Month +'-'+ Day +'T'+
Hour +':'+ Minute +':'+ Second +'.'+ Millisecond As DateTime2(7)) As DateValue
FROM CTEDateParts
), CTEFixedDates AS -- add 12 hours for hours between 1 and 8 a.m.
(
SELECT WorkRequestId,
DateValue,
CASE WHEN DATEPART(HOUR, DateValue) >= 1 AND DATEPART(HOUR, DateValue) <= 8 THEN
DATEADD(Hour, 12, DateValue)
ELSE
DateValue
END As FixedDate
FROM CTEDates
)
-- finally, select order by the FixedDate column
SELECT WorkRequestId
FROM CTEFixedDates
ORDER BY FixedDate
Results:
WorkRequestId
07052018080504623
07062018095201231
07062018102203805
07062018103718059
07062018110304836
07062018115356135
07062018120624983
07062018124035480
07062018012756663
07062018020148130
07062018070504623
07062018080504623
You can try the following:
select
*
from #t
order by left (WorkRequestId, 8) + (case when SUBSTRING(WorkRequestId, 9,2) between '01' and '07' then CAST(SUBSTRING(WorkRequestId, 9,2) + 12 AS CHAR(2)) else SUBSTRING(WorkRequestId, 9,2) end) + SUBSTRING(WorkRequestId, 11,7)
I'm trying to calculate the difference between two dates excluding the weekends and only count the time from 8pm - 6am. I want to calculate that difference in Days, Hours and Minutes.
For that I have this:
DECLARE #Start_Date DATETIME
DECLARE #End_Date DATETIME
SET #Start_Date = '2017-06-23 10:43:41.000'
SET #End_Date = '2017-06-27 11:58:52.000'
SELECT (DATEDIFF(dd, #Start_Date, #End_Date) + 1)
-(DATEDIFF(wk, #Start_Date, #End_Date) * 2)
-(CASE WHEN DATENAME(dw, #Start_Date) = 'Sunday' THEN 1 ELSE 0 END)
-(CASE WHEN DATENAME(dw, #End_Date) = 'Saturday' THEN 1 ELSE 0 END) AS [Time to First Atualization- Days],
datediff(hour, #Start_Date, #End_Date) - (datediff(wk, #Start_Date, #End_Date) * 48) -
case when datepart(dw, #Start_Date) = 1 then 1 else 0 end +
case when datepart(dw, #End_Date) = 1 then 1 else 0 end AS [Time to First Atualization- Hours],
datediff(minute, #Start_Date, #End_Date) - (datediff(wk, #Start_Date, #End_Date) * 2880) -
case when datepart(dw, #Start_Date) = 1 then 1 else 0 end +
case when datepart(dw, #End_Date) = 1 then 1 else 0 end AS [Time to First Atualization- Minutes]
The number of days the query return the correct value but to calculate the number of hours and minutes it's wrong...
How can I solve this?
Thanks!
I worked out something from scratch, and it seems to cover all your needs, though you can update us back if something's missing.
Considering it's a fresh start and coming from a different angle, you might discover certain techniques or ideas out of it. Also, it does seem simpler to me but maybe that's because I'm reviewing my own work...
One last note, I'll be relying on a trick I read before, that applies MIN and MAX in a row-wise fashion, abstract example:
SELECT MAX([value]) AS [MAX], MIN([value]) AS [MIN]
FROM (
VALUES (CURRENT_TIMESTAMP), (#Start_Date), (#End_Date), (NULL), (0)
) AS [data]([value])
First off, thought of figuring the amount of time outside start & end days:
SELECT MinutesExcludingStartAndEndDays = MAX([value])
FROM (VALUES (0), ((DATEDIFF(DAY, #Start_Date, #End_Date) - 1) * 840)) AS [data]([value])
Second, figuring the time during starting day, against 8pm (or end time if both days match):
SELECT MinutesOnStartDay = DATEDIFF(MINUTE, #Start_Date, MIN([value]))
FROM (VALUES (#End_Date), (DATETIMEFROMPARTS(YEAR(#Start_Date), MONTH(#Start_Date), DAY(#Start_Date), 20, 0, 0, 0))) AS [data]([value])
Third is very similar to second, however note that if start and end days were the same, we should not count both second and third. I decided to handle that with a CASE statement within third:
SELECT MinutesOnEndDayIfNotStartDay = CASE DATEDIFF(DAY, #Start_Date, #End_Date) WHEN 0 THEN 0 ELSE DATEDIFF(MINUTE, MAX([value]), #End_Date) END
FROM (VALUES (#Start_Date), (DATETIMEFROMPARTS(YEAR(#End_Date), MONTH(#End_Date), DAY(#End_Date), 6, 0, 0, 0))) AS [data]([value])
Fourth, if either start or end dates land on a weekend, it should be pushed away from there:
DECLARE #Mod int
SET #Mod = CONVERT(int, #Start_Date) % 7
IF #Mod IN (5, 6)
SET #Start_Date = DATEADD(DAY, CASE #Mod WHEN 5 THEN 2 WHEN 6 THEN 1 ELSE 0/0 END, DATETIMEFROMPARTS(YEAR(#Start_Date), MONTH(#Start_Date), DAY(#Start_Date), 6, 0, 0, 0))
SET #Mod = CONVERT(int, #End_Date) % 7
IF #Mod IN (5, 6)
SET #End_Date = DATEADD(DAY, CASE #Mod WHEN 5 THEN -1 WHEN 6 THEN -2 ELSE 0/0 END, DATETIMEFROMPARTS(YEAR(#End_Date), MONTH(#End_Date), DAY(#End_Date), 20, 0, 0, 0))
Lastly, the issue of having weekend days fully encompassed within your target period, for that have a look at this question, from the votes there I can only guess they worked it out already.
I want to use BETWEEN clause in this query and don't know how to do this
SELECT * FROM record
WHERE (DATEPART(yy, register_date) = 2009
AND DATEPART(mm, register_date) = 10
AND DATEPART(dd, register_date) = 10)
This gives the records from 5 hours ago until now
SELECT * FROM record
WHERE register_date BETWEEN DATEADD(HOUR, -5, GETDATE()) AND GETDATE()
It appears this might be what you want
select * from record
where register_date between '2017-10-1' and '2017-12-31'
Do note that if you want all records from the last day you might want to add time or pick the day after as the default time is 0:00
I would like to calculate the backlog for every week in the past month. Date format is in (MM/DD/YY)
| mutation | issued_date | queryno_i | status |
-----------------------------------------------
01/05/14 12/31/13 321 OPEN
01/02/14 08/01/13 323 CLOSED
01/01/14 06/06/13 123 OPEN
01/01/14 01/01/14 1240 CLOSED
01/02/14 01/01/14 1233 OPEN
01/03/14 01/03/14 200 CLOSED
01/05/14 01/04/14 300 OPEN
01/06/14 01/05/14 231 OPEN
01/07/14 01/06/14 232 CLOSED
01/09/14 01/10/14 332 OPEN
01/11/14 01/11/14 224 CLOSED
01/15/14 01/14/14 225 CLOSED
01/16/14 01/15/14 223 OPEN
I want my result set to look like this:
WeekNum | Opened | Closed | Total Open
--------------------------------------
1 4 3 4 <= (2-4)+ data in week 2 so (2-4)+(1-2)+7
2 4 2 6 <= (1-2)+7
3 2 1 7 <= total count
My Code is below however I am not sure how to query the last part. I am not even sure if this is possible or not.
WITH
issued_queries AS
(
SELECT DATEPART(wk, issued_date) AS 'week_number'
,COUNT(queryno_i) AS 'opened'
FROM t.tech_query
WHERE DATEADD(D,-12,issued_date) > GETDATE()-40
GROUP BY DATEPART(wk, issued_date)
),
closed_queries AS
(
SELECT DATEPART(wk, mutation) AS 'week_number'
,COUNT(queryno_i) AS 'closed'
FROM t.tech_query
WHERE status=3 AND DATEADD(D,-12,issued_date) > GETDATE()-40
GROUP BY DATEPART(wk, mutation)
),
total as
(
SELECT COUNT(*) AS 'total'
FROM t.tech_query
WHERE status!='3'
)
SELECT issued_queries.week_number
, issued_queries.opened
, closed_queries.closed
FROM issued_queries JOIN closed_queries
ON (issued_queries.week_number = closed_queries.week_number)
ORDER BY week_number
Backlog for every week in the past month.
I've taken this to mean last 4 weeks, as that appears to be what you are doing.
Assuming "mutation" represents the date a record was updated (maybe set to closed).
So first, I generate a list of dates, so that way there will be an answer for week number X even if there are no new/closed records.
declare #SundayJustGone datetime
-- We need to get rid of the time component, done through convert.
set #SundayJustGone = convert(date, dateadd(d, 1-DATEPART(dw, getdate()), getdate()))
-- If earlier than sql 2008, can get rid of time component through: set #SundayJustGone = SELECT DATEADD(dd, 0, DATEDIFF(dd, 0, #SundayJustGone))
;with
Last4Weeks as
(
-- Get the sunday of the week just gone.
select #SundayJustGone as SundayDate -- Sunday just gone
union all
select dateadd(d, -7, SundayDate) -- Get the previous Sunday
from Last4Weeks
where dateadd(d, -7, SundayDate) > dateadd(Wk, -4, #SundayJustGone) -- where the new date is not more than 4 weeks old
)
select A.SundayDate,
DATEPART(wk, DateAdd(d, -1, A.SundayDate)) as Week_Number, -- SQL considers Sunday the first day of the week, so we need to move it back 1 day to get the right week
(select count(*)
from t.tech_query
where issued_date between DateAdd(d, -6, A.SundayDate) and A.SundayDate -- Was issued this week. (between monday - sunday)
) as Opened,
(select count(*)
from t.tech_query
where status = 3 -- where it is closed
and mutation between DateAdd(d, -6, A.SundayDate) and A.SundayDate -- and the mutation was this week. (between monday - sunday)
) as Closed,
(select count(*)
from t.tech_query
where (status != 3 or datediff(d, mutation, A.SundayDate) < 0 ) -- Is still open, or was closed after this week.
and datediff(d, issued_date, A.SundayDate) >= 0 -- and it was issued on or before the sunday.
) as TotalOpen
from Last4Weeks as A
hopefully this helps.
the results are different to yours, as I assume Monday is the first day of the week. To change start of week back to sunday, saturday needs to be considered end of week, so, change the set #SundayJustGone = convert(date, dateadd(d, 1-DATEPART(dw, getdate()), getdate())) to set #SundayJustGone = convert(date, dateadd(d, -DATEPART(dw, getdate()), getdate())) (1 removed)