I am trying to make a sql query in which I want to count the people comprised in three ranges:
Tomorrow (from 06:00 a.m. to 12:00 p.m.)
Afternoon (from 12:00 p.m. to 9:00 p.m.)
Night (from 9:00 p.m. to 6:00 a.m.)
I have two attributes, check in time and check out time which have the following format:
2020-05-20 12:10:29.000
I am doing it in the following way but it does not work, for example, in the night:
select (case when datepart(hour, dateIn) > datepart(hour, '21')) and
datepart(minute, dateIn) > datepart(minute, '00'))
If I understand correctly, you can subtract 6 hours to get the date and then use time comparisons for the shift. So, I think you want:
select convert(date, dateadd(hour, -6, t.datein)), v.shift, count(*)
from t cross apply
(values (case when convert(time, t.datein) < '06:00:00' then 'night'
when convert(time, t.datein) < '12:00:00' then 'morning'
when convert(time, t.datein) < '21:00:00' then 'afternoon'
else 'night'
end)
) v(shift)
group by convert(date, dateadd(hour, -6, datein)), v.shift;
Related
I am trying to filter a table between 4 pm of previous day and 4am of current day but am at loss of how to query that.
Something like:
WHERE
dateColumn >= DATEADD(DAY, -1, GETDATE()) AND dateColumn <= GETDATE()
AND DATEPART(hh, dateColumn) >= 16 AND DATEPART(hh, dateColum) <= 4
I realize the second line in WHERE statement is obviously incorrect and will not return any results but that is to give an idea of what I am trying to do. All help is appreciated!
There are various ways you could do this, this gets the datetime at 1600 yesterday and 1600 today.
WHERE dataColumn >= dateadd(hour, -8, convert(datetime, convert(date, getdate())))
AND dateColumn <= dateadd(hour, 16, convert(datetime, convert(date, getdate())));
I am working on a query that I hope to be able to use to query against a database for a specific range of time on a specific date. If I query for a full day of data I get the correct data returned. One row per hour of data available (0 - 23).
WHERE Documents.CreationTime BETWEEN '2014-10-01 00:00:00.000' AND '2014-10-01 23:59:59.999'
If I attempt to query for a portion of the day, the results are unusual.
WHERE Documents.CreationTime BETWEEN '2014-10-01 00:00:00.000' AND '2014-10-01 06:00:00.000'
Part day query returns: (Note the hours jump from 0 to 19)
Hours Faxes Good Page Count
0 3 4
19 15 58
20 4 9
21 8 42
22 2 4
23 4 12
Here is my reduced query I created to try and resolve the issue.
SELECT DATEPART(hour, DATEADD(HH, - DATEDIFF(Hour, GETDATE(), GETUTCDATE()), Documents.CreationTime)) AS Hours
,COUNT(*) AS Faxes
,SUM(goodpagecount) AS [Good Page Count]
FROM Documents
JOIN Users
ON Documents.OwnerID = Users.handle
JOIN Groups
ON Users.GroupID = Groups.handle
JOIN History
ON History.OWNER = Documents.handle
JOIN HistoryTRX
ON History.handle = HistoryTRX.handle
WHERE Documents.CreationTime BETWEEN '2014-10-01 00:00:00.000'
AND '2014-10-01 06:00:00.000'
GROUP BY DATEPART(hour, DATEADD(HH, - DATEDIFF(Hour, GETDATE(), GETUTCDATE()), Documents.CreationTime))
ORDER BY DATEPART(hour, DATEADD(HH, - DATEDIFF(Hour, GETDATE(), GETUTCDATE()), Documents.CreationTime))
Any suggestions as to what I am missing or improvements?
EDIT- More details
The "Documents.CreationTime" is in UTC. I am looking to have the "Hours" column correspond to local time. In this case UTC -5 as of this entry.
How about using the DATEADD function in your where clause:
WHERE Documents.CreationTime >= '20141001' AND Documents.CreationTime <= DATEADD(HOUR,6,'20141001')
Interesting Blog on the comment made by Lamak written by Aaron Bertrand :
What do BETWEEN and the devil have in common?
Based on suggestions provided in response to my question, I came up with the following new query:
SELECT DATEPART(hour, DATEADD(HH,-DATEDIFF(Hour,GETDATE(),GETUTCDATE()),Documents.CreationTime)) AS Hours ,COUNT(*) AS Faxes,SUM(goodpagecount) AS [Good Page Count]
FROM Documents
JOIN Users ON Documents.OwnerID=Users.handle
JOIN Groups ON Users.GroupID=Groups.handle
JOIN History ON History.Owner=Documents.handle
JOIN HistoryTRX ON History.handle=HistoryTRX.handle
WHERE DATEADD(HH,-DATEDIFF(Hour,GETDATE(),GETUTCDATE()),Documents.CreationTime) >= '2014-10-01 00:00:00.000' and DATEADD(HH,-DATEDIFF(Hour,GETDATE(),GETUTCDATE()),Documents.CreationTime) <= '2014-10-03 08:00:00.000'
GROUP BY DATEPART(hour, DATEADD(HH,-DATEDIFF(Hour,GETDATE(),GETUTCDATE()),Documents.CreationTime))
ORDER BY DATEPART(hour, DATEADD(HH,-DATEDIFF(Hour,GETDATE(),GETUTCDATE()),Documents.CreationTime))
My changes are to the "WHERE" statement by adding my UTC compensation. The "WHERE" now matches the "SELECT".
Before:
WHERE Documents.CreationTime >= '2014-10-01 00:00:00.000' and Documents.CreationTime <= '2014-10-03 08:00:00.000'
After:
WHERE DATEADD(HH,-DATEDIFF(Hour,GETDATE(),GETUTCDATE()),Documents.CreationTime) >= '2014-10-01 00:00:00.000' and DATEADD(HH,-DATEDIFF(Hour,GETDATE(),GETUTCDATE()),Documents.CreationTime) <= '2014-10-03 08:00:00.000'
Also removed the BETWEEN keyword as it may not be as precise for results as I would like.
The results now look like:
Hours Faxes Good Page Count
0 3 4
1 5 9
3 9 50
4 8 16
5 14 40
am working with MS SQL express and Ignition SCADA by http://www.inductiveautomation.com/
In the SCADA package you are able to create tags from SQL query's. I am trying to use SQL tags to calculate the average packages per minute in a 30min time frame. I was able to do this with two tags and an expression
SELECT MAX(L8Total)
FROM Slicing_tot
WHERE t_stamp BETWEEN DATEADD(minute, -30, GETDATE()) AND GETDATE()
SELECT MIN(L8Total)
FROM Slicing_tot
WHERE t_stamp BETWEEN DATEADD(minute, -30, GETDATE()) AND GETDATE()
What I would like to do from here is store the expressions value and find the max and average for the last 30 days based on time. But I have no idea how to filter 30days of information at a certain time
IE what was the max packages per minute we had at 10:30 from the last 30 days
IE what was the average packages per minute we had at 11:45 form the last 30 days
Please keep in mind that I am new to SQL
SELECT DATEPART(MINUTE, t_stamp)
,MAX(L8Total)
,MIN(L8Total)
FROM Slicing_tot
WHERE ( CONVERT(DATE, t_stamp) >= CONVERT(DATE, GETDATE() - 30)
AND CONVERT(DATE, t_stamp) <= CONVERT(DATE, GETDATE())
)
AND ( CONVERT(TIME, #variable) >= '22:30'
AND CONVERT(TIME, #variable) <= '23:00'
)
GROUP BY DATEPART(MINUTE, t_stamp)
GETDATE()-30 will get you datetime of today minus 30 days ago. Since you are working with datetime field it is best to convert it to date to make sure that you get correct date range. Use of >= and <= is better than between because you is always clear what you doing. Read #Aaron's blog
than for the second part just convert your datetime column to time to limit to specific range during the day.
The following would select between 10 & 11 AM over those 30 days
SELECT MIN(L8Total)
FROM Slicing_tot
WHERE t_stamp BETWEEN DATEADD(dd, -30, GETDATE()) AND GETDATE()
and Datepart(hh,t_stamp) between 10 and 11
or you could compare the time part of the t_stamp to time
SELECT MIN(L8Total)
FROM Slicing_tot
WHERE t_stamp BETWEEN DATEADD(dd, -30, GETDATE()) AND GETDATE()
and convert(time, t_stamp) between '10:30:00.000' and '10:31:00.000'
which would give you the results between 10:30 and 10:31 inclusive of the end points over the last 30 days.
ApptStart
2005-02-18 10:00:00.000
2005-02-18 13:00:00.000
2005-02-18 11:00:00.000
2005-02-21 09:00:00.000
2005-02-18 15:30:00.000
2005-02-18 14:30:00.000
.
.
.
I have a column in our database that looks like the above. I want to count appointments for the month for a given doc. On Fridays most of them do a half day. So I do not want to count Fridays with appointments only in the morning. If the appointment is in the afternoon, after 12:00:00.000 I want to include that day in the distinct count.
So far I have:
SELECT
ScheduleDays = count(distinct CONVERT(datetime, convert(char(12), a.ApptStart, 1)))
FROM Appointments a
WHERE
ApptKind = 1 AND
--filter on current month
a.ApptStart >= ISNULL(DATEADD(month, DATEDIFF(month, 0, GETDATE()), 0),'1/1/1900') AND
a.ApptStart < ISNULL(DATEADD(month, DATEDIFF(month, 0, GETDATE())+1, 0),'1/1/3000') AND
--Filter on doctor
a.ResourceID in (201)
This worked when I counted every day with appointments on it, but like I said I need to exclude those half days.So I was thinking about only looking at the last right chars of the ApptStart and comparing it x > noon in a case inside the distinct count...
I tried the following, but it did not work:
ScheduleDays = count(distinct case when (Right(a.ApptStart, 12)) > '12:00:00:000' then 1 else 0 END)
Thanks in advance!
EDIT
I tried:
SELECT
ScheduleDays=COUNT(DISTINCT(CAST(datediff(d,0,a.ApptStart) as datetime)))
FROM Appointments a
WHERE
ApptKind = 1 AND
--filter on current month
a.ApptStart >= ISNULL(DATEADD(month, DATEDIFF(month, 0, GETDATE()), 0),'1/1/1900') AND
a.ApptStart < ISNULL(DATEADD(month, DATEDIFF(month, 0, GETDATE())+1, 0),'1/1/3000')AND
--filter all days that aren't Friday, and then give you all Fridays with an hour > 12.
DATENAME(weekday, a.ApptStart) <> 'Friday' OR DATEPART(hour, a.ApptStart) > 12 AND
--Filter on doctor
a.ResourceID in (201)
for 1808 as the count
You probably want to treat dates as dates, rather than strings. You can determine whether a particular timestamp is on a Friday -- or the hour of a timestamp -- using DATEPART, without having to CONVERT it into a CHAR:
datename(weekday, timestamp_value) -- returns Friday
datepart(weekday, timestamp_value) -- returns either 5 or 6, depending on the value of SET DATEFIRST. (Get day of week in SQL 2005/2008)
datepart(hour, timestamp_value) -- returns hour part
Using these, you can test whether a timestamp is on Friday at or after noon by checking if datepart(weekday, timestamp_value) = 6 and datepart(hour, timestamp_value) >= 12.
bendataclear pointed out that you're using distinct on a case statement which can only ever return 0 or 1, so your total will only ever be 0, 1, or 2. If you're trying to determine which days the doctors worked more than half a day, you'll need to select distinct dates --
SELECT COUNT(DISTINCT(CAST(datediff(d,0,timestamp_value) as datetime)))
FROM table_name
WHERE DATENAME(weekday, timestamp_value) <> 'Friday' OR DATEPART(hour, timestamp_value) > 12
AND the rest of your filters here
The WHERE clause there will give you all days that aren't Friday, and then give you all Fridays that have an hour > 12.
I have a SQL Server 2005 table that contains records with a UTC/GMT date field.
I need to have the records GROUPed BY and ORDERed by the "day of the week" and "hour of the day". Giving 7*24=168 groups. The output would look like:
Sun 12am
Sun 1am
Sun 2am
.... etc
Mon 12am
Mon 1am
.... etc
.... etc
Sat 10pm
Sat 11pm
Everything works fine until I try to convert things to my local time zone.
Doing the conversion inside SQL:
SELECT MIN(Key),MIN(SavedOn),
FROM MyTable
GROUP BY (DatePart(WEEKDAY, SavedOn)*24.0) + DatePart(HOUR, SavedOn) - (5.0/24.0)
ORDER BY (DatePart(WEEKDAY, SavedOn)*24.0) + DatePart(HOUR, SavedOn) - (5.0/24.0)
Or doing the conversion in my own code AFTER sorting/getting the records in UTC:
SELECT MIN(Key),MIN(SavedOn),
FROM MyTable
GROUP BY (DatePart(WEEKDAY, SavedOn)*24.0) + DatePart(HOUR, SavedOn)
ORDER BY (DatePart(WEEKDAY, SavedOn)*24.0) + DatePart(HOUR, SavedOn)
(my own math here)
Either way... 5 records will appear "out of order". The end of the week records (Sat PM)
appear at the beginning of the week... not the end... where they belong.
Any idea on what I'm doing wrong?
Floating point math is imprecise. Multiplying by 24.0 invites border errors.
Instead of adding the numbers
GROUP BY (DatePart(WEEKDAY, SavedOn)*24.0) + DatePart(HOUR, SavedOn)
sort on two fields instead:
GROUP BY DatePart(WEEKDAY, SavedOn), DatePart(HOUR, SavedOn)
Here is what I would do. I am not sure I totally understand what you are trying though:
SELECT DatePart(WEEKDAY, SavedOn), DatePart(HOUR, SavedOn) , min(key)
FROM MyTable
GROUP BY DatePart(WEEKDAY, SavedOn), DatePart(HOUR, SavedOn)
ORDER BY 1, 2
If your approach to converting is just to add 5 hours, then do it every time you see SavedOn , like this:
SELECT DatePart(WEEKDAY, SavedOn+5.0/24.0), DatePart(HOUR, SavedOn+5.0/24.0) , min(key)
FROM MyTable
GROUP BY DatePart(WEEKDAY, SavedOn+5.0/24.0, DatePart(HOUR, SavedOn+5.0/24.0)
ORDER BY 1, 2