I have a question about how to “pivot/total” (for want of a better word) some data around in SQL server. The data is basically staff shifts and then hours lost from those shifts. So for example I have a record in one table
Staff_ID Shift_start Shift_end
37 09:00 17:30
And then we would give that person a lunch in another table
Staff_ID Start End
37 13:00 14:00
Of course we have more agents throughout the day and the scheme above is simplified but you get the idea. This is then transformed into the number of staff in 15 minutes
Interval Staff
09:00 5
09:15 7
09:30 6
And so on.
At the moment SQL server stores all of this but to “total” the agents up I have to bring things into Access and using arrays work out the number of staff in each 15 minute period and then save this data back to the database. It’s a quick process (<1500ms) but what I’m looking for is a way to do this in SQL server itself and not have to bring things to Access and write it back.
Am I barking up the wrong tree with this one?
EDIT:
I'm using SQL server 2008R2 Express
Update
Try this:
;with Intervals(start) as --00:00 - 23:45
(
select dateadd(minute, 0,0)
union all
select dateadd(minute, 15, start) from Intervals
where datediff(hour, 0, dateadd(minute, 15, start))<24
)
select convert(varchar, i.start, 108) [Interval], count(*) [Staff]
from Intervals i
join
(
select cast('09:31:29' as datetime) [start], cast('17:11:29' as datetime) [end] union all
select cast('10:43:12' as datetime), cast('18:21:29' as datetime) union all
select cast('11:59:53' as datetime), cast('19:51:29' as datetime)
)s
on cast(convert(varchar(10), s.start, 108)as datetime) <= i.start
and dateadd(minute, 15, i.start) <= cast(convert(varchar(10), s.[end], 108) as datetime)
group by convert(varchar, i.start, 108)
You have a few approaches you could try. One would be to take exactly what you have in Access and convert it to SQL. If there's part of that you're not sure how to do, post it here and we can help.
Another would be to use a cursor (as opposed to a single set function) to iterate through either each 15 minute time period, loading staff working during that period, or each staff person's schedule, populating all of their working 15-minute time periods. You may be doing this in Access already, I can't tell.
Since they're the same 15-minute periods each day, you can store the times in a table and do an outer join on them, but the performance could be worse than your Access process.
Related
I want to query data that happened between 6:15 and 7:15, 7:15:01 and 8:15 and so forth. So far I am only able to do the following:
Select *
From table
Where datepart(hh, t_stamp) = 7
and datepart(day, t_stamp) = day(getdate())
I am selecting all data that happens between 7:00 and 7:59:59....
I tried googling it. Found something using unix_timestamp, but that does not work in Microsoft SQL Server. I've been wrecking my brain but as a SQL noob (I am used to "ladder logic" in PLC programming) this is way out of my comfort zone.
If you are looking for fetching the data between a specific time, let's say 06:15 to 07:15 for any date, then convert the datetime to time and use it in the where clause.
Query
select * from your_table_name
where cast(t_stamp as time) between '06:15:00' and '07:15:00';
If you need it only for today's date, then add that condition too in the Where clause.
select * from your_table_name
where cast(t_stamp as time) between '06:15:00' and '07:15:00'
and cast(t_stamp as date) = cast(getdate() as date);
I have a requirement to pull records from SQL Server from a specific hour every day, say at 4 PM.
So if I am running query at 3 PM today, it should pull records from previous day 4 PM till today 3 PM (23 hours).
On the other hand, if run query at 4:30 PM today, it should pull query from today 4 PM to 4:30 PM (only for half an hour) and so on
How could I do this in plain SQL in SQL Server?
Here is how I would do it:
SELECT *
FROM TableName
WHERE ColumnName <= GETDATE()
AND ColumnName >=
CASE WHEN DATEPART(HOUR, GETDATE()) < 4 THEN
DATEADD(HH, 4, CAST(CAST(GETDATE()-1 AS date) AS datetime))
ELSE
DATEADD(HH, 4, CAST(CAST(GETDATE() AS date) AS datetime))
END
Points of interest:
CAST(GETDATE() AS date) will return the date part of the current datetime.
Casting back to datetime allows you to use DateAdd to get the hour you want
using -1 with date values subtracts a day from the date (+1 will add a day, of course)
using the CASE...WHEN allows you to write a single where clause that fits both scenarios described in the question.
Please try the below query, i have created it for stored procedures that had been modified on specific date:
Select * from sys.procedures where CONVERT(date,modify_date,101) =
CONVERT(date,DATEADD(DD,-5, GETDATE()),101)
AND DATEPART(hh,modify_date) >= 1 AND DATEPART(hh,modify_date) <= 22
You can pass "CONVERT(date,DATEADD(DD,-5, GETDATE()),101)" GEDATE only instead to - minus five days, that was done only to fetch records for me.
and in hours you can specify the range as you want.
Hope this will work for you.
I think this might help you
select 1 from table where Col1 between case when hour(getdate())>4 then convert(datetime,convert(varchar(20),year(getdate()))+'-'+convert(varchar(20),month(getdate()))+'-'+convert(varchar(20),day(getdate()))+' 04:00') else dateadd(hh,-23,getdate()) end and getdate()
I have one table in SQL Server where I want to add a column that will show this year's date for the exact transition dates for European Summer Time.
European Summer Time is observed across three time zones, beginning at 01:00 UTC/WET on the last Sunday in March and ending at 01:00 UTC on the last Sunday in October each year.
How do you change this into a SQL function?
On Wikipedia I was able to find this:
The formula used to calculate the beginning of European Summer Time is
Sunday (31 − ((((5 × y) ÷ 4) + 4) mod 7)) March at 01:00 UTC
https://en.wikipedia.org/wiki/Summer_Time_in_Europe
Be careful. DST is a non-technical, but political policy and can vary over time (countries change DST adjustments all the time) which requires an up-to-date timezone database.
SQL Server itself is not concerned with timezones: it does not perform any timezone conversion itself, only UTF-offset conversion (when using datetimeoffset when the instantaneous local-to-UTC conversion is known). It cannot tell you anything about zone locations or future offsets, as those are arguably business rules that belong outside the domain of the persistence layer (i.e. SQL Server). When storing values in a database always used either UTC datetime or datetimeoffset values. Use UTC datetime when zone information is irrelevant to the user (i.e. don't invent your own datetime+int system, use datetimeoffset).
Along those lines, SQL Server does not provide any API or functionality for accessing the system (the Windows OS') timezone database from T-SQL code.
You would need to do this from application code. In .NET you can use the TimeZoneInfo class which uses Windows' timezone database to get the DST dates:
TimeZoneInfo.AdjustmentRule.DateStart
TimeZoneInfo.AdjustmentRule.DateEnd
TimeZoneInfo.AdjustmentRule.DaylightTransitionStart
TimeZoneInfo.AdjustmentRule.DaylightTransitionEnd
https://msdn.microsoft.com/en-us/library/system.timezoneinfo.adjustmentrule(v=vs.110).aspx
Depending on what the criteria you're inputting into whatever function you want to produce here is, the specific code is going to be different.
The following, for example, produces a list of the dates/times for the next 100 years in the timezone this is run in.
; WITH C1(N) AS (SELECT 1 FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) T(N))
, C2(N, RN) AS (SELECT 1, ROW_NUMBER() OVER (ORDER BY NEWID()) FROM C1 a CROSS JOIN C1 b)
, TYears AS (SELECT YEAR(GETDATE()) + RN - 1 [Years] FROM C2)
SELECT DATEADD(hh
, DATEDIFF(hh, GETUTCDATE(), GETDATE())
, DATEADD(dd
, 0 - (1 + DATEDIFF(dd, 0, CONVERT(DATE, CONVERT(NVARCHAR, [Years]) + '-03-31')) % 7) % 7
, CONVERT(DATETIME, CONVERT(NVARCHAR, [Years]) + '-03-31 01:00:00'))) [StartDateTime]
, DATEADD(hh
, DATEDIFF(hh, GETUTCDATE(), GETDATE())
, DATEADD(dd
, 0 - (1 + DATEDIFF(dd, 0, CONVERT(DATE, CONVERT(NVARCHAR, [Years]) + '-10-31')) % 7) % 7
, CONVERT(DATETIME, CONVERT(NVARCHAR, [Years]) + '-10-31 01:00:00'))) [EndDateTime]
FROM TYears
The basic premise being find the last Sunday of March for that year, find the UTC +/- value, add it to 1AM of the last Sunday of March.
I need to display running server status, in an asp.net grid view using c#, for the last 24 hours in 5 minute increments. The data is in SQL Server records of the form: HostName, RecordDate, RecordTime, Status. I need to transform the data into tabular format to load a grid view control. Transform to something like: HostName, Date, 00:00 status, 00:05 status, ..., 23:55 status. One of the problems, of course, is the user can access the web page at any time. The column names must be the 5 minute increment time, as 15.30, 15.35, etc. They'll always be the same, as 24 hours will be displayed, but will be in a different order, and potentially cross dates, depending upon when the user logs into the web site. I hope I've explained this well enough. All options are on the table: linq, linq to sql, linq to xml, etc.
Thanks for any help.
I will offer a T-SQL solution. You need a date table that holds the 5-minute intervals for the day in question. Left join that with your AccessLog (or whatever it's called) table where the access time is within each time range, and do whatever aggregations you want. This will give you the vertical list. Then you need to PIVOT that to make your TimeRanges into columns (search for SQL server PIVOT operator).
Below is the rough SQL. After that, you just need to wrap the results into a pivot.
declare #myDate SMALLDATETIME = '20130415';
;with TimeRanges as (
SELECT TOP 288 DateAdd(minute, (Row_Number() over (order by sc1.Name) -1) * 5 , #myDate) TimeRangeMin
, DateAdd(minute, Row_Number() over (order by sc1.Name) * 5 , #myDate) TimeRangeMax
FROM Master.dbo.SysColumns sc1, Master.dbo.SysColumns sc2
)
select convert(varchar(5), TimeRangeMin, 114) AS TimeRange, COUNT(*)
from TimeRanges t
LEFT JOIN AccessLog a on a.AccessTime >= t.TimeRangeMin and a.AccessTime < t.TimeRangeMax
GROUP BY convert(varchar(5), TimeRangeMin, 114);
I need to produce a SQL report showing the number of times a particular event happened in each hourly period during the day. My table has a date/time column on it containing the time the event occurred.
How do I do a count of the number of rows that fall within each each hourly period during the day?
So I need to see output like this...
10:00 - 11:00 12 times
11.00 - 12:00 53 times
12:00 - 13:00 5 times etc
I'm guessing it would be a Group By, but how do you group by each hour?
Thanks in advance.
SELECT DATEPART(hh, DateTimeColumn), COUNT(*)
FROM
TableName
GROUP BY
DATEPART(hh, DateTimeColumn)
ORDER BY
DATEPART(hh, DateTimeColumn)
Seans solution will only work with 24 hours worth of data as datepart dd only returns 0-23.
If you need to process more than that, you'll need to add in the day too.
Something like:
SELECT CAST(DateTimeColumn AS INT) [day],DATEPART(hh, DateTimeColumn), COUNT(*)
FROM
TableName
GROUP BY
CAST(DateTimeColumn AS INT),
DATEPART(hh, DateTimeColumn)
ORDER BY
CAST(DateTimeColumn AS INT),
DATEPART(hh, DateTimeColumn