avg data of last week in a specific hour - sql

I created a sql query that return a AVG data of last hour. Example: right now are 11h this return the average of data at 10h.
Now I need to improve my query, I want the average data of last hour and the average data of all days of the last week in the same hour. How can I do that ?
This is my query:
DECLARE #begin_time smalldatetime,
#end_time smalldatetime
SET #begin_time = CONVERT(VARCHAR(19), GETDATE(), 120)
SET #begin_time = DateADD(HOUR, -1, #begin_time)
SET #begin_time = convert(char(14),#begin_time,121)+'00:00'
SET #end_time = CONVERT(VARCHAR(19), GETDATE(), 120)
SET #end_time = DateADD(HOUR, -1, #end_time)
SET #end_time = convert(char(14),#end_time,121)+'59:00'
SELECT u.name,
YEAR(dpr.reading_time) AS "year",
MONTH(dpr.reading_time) AS "month",
DAY(dpr.reading_time) AS "day",
DATEPART(HOUR, dpr.reading_time) AS "hour",
AVG(CAST(CAST(dpr.value as DECIMAL(22, 5))/POWER(10, 5) as DECIMAL(20, 5))) * 1 AS "data"
FROM example.users u
INNER JOIN example.datapoint_readings dpr
ON dpr.datapoint_id = u.datapoint_id
WHERE reading_time BETWEEN #begin_time AND #end_time
GROUP BY u.name, YEAR(dpr.reading_time), MONTH(dpr.reading_time), DAY(dpr.reading_time), DATEPART(HOUR, dpr.reading_time)
ORDER BY u.name, YEAR(dpr.reading_time), MONTH(dpr.reading_time), DAY(dpr.reading_time), DATEPART(HOUR, dpr.reading_time)

If I understand correctly, you want to see the previous hour on each date for some period of time:
SELECT u.name, cast(dpr.reading_time as date) as reading_time_date,
DATEPART(HOUR, dpr.reading_time) as "hour",
AVG(CAST(CAST(dpr.value as DECIMAL(22, 5))/POWER(10, 5) as DECIMAL(20, 5))) * 1 AS "data"
FROM example.users u INNER JOIN
example.datapoint_readings dpr
ON dpr.datapoint_id = u.datapoint_id
WHERE datepart(hour, reading_time) = datepart(hour, dateadd(hour, -1, getdate())) AND
reading_time >= dateadd(day, -7, getdate())
GROUP BY u.name, cast(dpr.reading_time as date),
DATEPART(HOUR, dpr.reading_time)
ORDER BY u.name, cast(dpr.reading_time as date),
DATEPART(HOUR, dpr.reading_time)
The important difference is the WHERE clause. The first condition extracts the hour for comparison. The second limits the results only to the past week.

Related

How to insert missing rows in a table?

I have a table with the following columns (checkdate datetime, duration int). I have this stored procedure which groups the data per hour.
CREATE PROC [dbo].[last_hours]
#hours int
AS
BEGIN
SELECT
CAST(checkdate as date) AS ForDate,
DATEPART(hour, checkdate ) AS OnHour,
AVG(duration) AS Duration
FROM
pings
WHERE
DATEDIFF(hour, checkdate , GETDATE()) <= #hours
GROUP BY
CAST(checkdate as date),
DATEPART(hour, checkdate )
END
The proc works fine. However I have situations where data for certain hours is not available. In this case I need to add an extra "empty" row for every missing hour before returning the result to the client.
Is it possible to do this in an easy way without resorting to cursors and loops?
this uses recursive cte to generate a list of checkdate and then LEFT JOIN to the table.
CREATE PROC [dbo].[last_hours]
#hours int
AS
BEGIN
WITH hours as
(
SELECT checkdate = DATEADD(hour, -#hours, GETDATE())
UNION ALL
SELECT checkdate = DATEADD(hour, 1, checkdate)
FROM hours
WHERE checkdate < GETDATE()
)
SELECT
CAST(h.checkdate as date) AS ForDate,
DATEPART(hour, h.checkdate ) AS OnHour,
AVG(p.duration) AS Duration
FROM
hours h
LEFT JOIN pings p ON CAST(h.checkdate as date) = CAST(p.checkdate as date)
AND DATEPART(hour, h.checkdate) = DATEPART(hour, p.checkdate)
GROUP BY
CAST(h.checkdate as date),
DATEPART(hour, h.checkdate )
ORDER BY ForDate, OnHour
END

How to get records in specific time range when the time range is between two days

I'm trying to query a specific range of time:
i.e. 1/1/2021 - 1/31/2021
between 5:55AM - 5:00AM (next day) for all days in above date
You need to extract time portion from your timestamps (datetime type for T-SQL) and filter by them in addition to dates filter.
db<>fiddle here
declare
#dt_from datetime
, #dt_to datetime
, #tm_from time
, #tm_to time
, #dt datetime
;
select
#dt = convert(datetime, '2021-02-10 11:48:36', 120)
, #dt_from = convert(date, '2021-02-01', 23)
, #dt_to = convert(date, '2021-02-28', 23)
, #tm_from = convert(time, '05:55:00', 120)
, #tm_to = convert(time, '05:00:00', 120)
;
with a as (
select #dt as dt union all
select dateadd(hour, 20, #dt) union all
select dateadd(hour, -15, #dt) union all
select dateadd(hour, -6, #dt) union all
select dateadd(day, -30, #dt) union all
select convert(datetime, '2021-02-01 00:01:02', 120) union all
select convert(datetime, '2021-02-28 20:01:02', 120)
)
select *
from dt
/*Restrict dates*/
where dt >= #dt_from
and dt < dateadd(day, 1, #dt_to)
and (
/*Exclude time intervals between 05:00 and 05:55*/
cast(dt as time) <= #tm_to
or cast(dt as time) >= #tm_from
)
Or if you need only the cases when entire time frame falls into your dates (e.g. exclude times from 00:00 till 05:00 for start date and from 05:55 till 23:59:59 of end date):
select *
from dt
where dt between #dt_from and #dt_to
and (
/*Exclude time intervals between 05:00 and 05:55*/
cast(dt as time) <= #tm_to
or cast(dt as time) >= #tm_from
)
/*Exclude time intervals at boundary dates*/
and not(
(cast(dt as date) = #dt_from and cast(dt as time) <= #tm_to)
or (cast(dt as date) = #dt_to and cast(dt as time) >= #tm_from)
)

How to extract data from 1st day of the month till today's date -1

I am trying to extract all the data that has the datetime from 1st day of the month till yesterday, for example:
01/06/2017 - 22/06/2017
I have used this code:
Select *
from testDb.dbo.Company1
WHERE MONTH(CreatedDate) = MONTH(dateadd(dd, -1, GetDate())) AND
YEAR(CreatedDate) = YEAR(dateadd(dd, -1, GetDate()))
EDIT
My column for CreatedDate, its data type is DateTime. Not sure if there is any difference tho.
But this prints out all the data from 01/06/2017 - 23/06/2017. What code should I write such that it will print all data till (today's date-1)? Thanks for the help and have a great day!
Instead of comparing the month and year components separately, try bounding your result set using a range of two complete data points, one being the start of the month, and the other being yesterday.
SELECT *
FROM testDb.dbo.Company1
WHERE
CreatedDate BETWEEN DATEADD(month, DATEDIFF(month, 0, GETDATE()), 0) AND
DATEADD(day, -1, CAST(GETDATE() AS date))
Demo
Try this query --
SELECT *
FROM testDb.dbo.Company1
WHERE DATEPART(Month, CreatedDate) = Datepart(Month, GETDATE())
AND DATEPART(Day, CreatedDate) <= DATEPART(Day, Getdate())
Edit:
SELECT *
FROM testDb.dbo.Company1
WHERE DATEPART(Month, CreatedDate) = Datepart(Month, GETDATE())
AND DATEPART(Day, CreatedDate) < DATEPART(Day, Getdate())
Edit 2:
SELECT CONVERT(VARCHAR(30),CreatedDate,120) As [CreatedDate]
FROM testDb.dbo.Company1
WHERE DATEPART(Month, CreatedDate) = Datepart(Month, GETDATE())
AND DATEPART(Day, CreatedDate) < DATEPART(Day, Getdate())
This though wont work when today is the first day of the month
SELECT *
FROM your_table
WHERE createdDate BETWEEN
CAST('1 ' + DateName(month, GetDate()) + ' ' +Year(GetDate()) as datetime)
AND DATEADD(day, -1, GETDATE() )
I think this where clause does what you want:
where createdDate >= dateadd(month, 0, datediff(month, 0, getdate())) and
createdDate < cast(getdate() as date)

Select every date where date is equal to today's date minus 1 day - Not working with dateadd on Month/year - T SQL

Like the title says, I am trying to build a query that selects all records from a database table where the date is equal to yesterdays date.
The date column in the table is however of the format datetime (with hours, minutes, seconds as well) so I do the select based on the dates year, month and day (times don't matter as long as the date is yesterday).
To achieve this I have build the following query:
SELECT
*
FROM
qryTouchBoekingen
WHERE
(DATEPART(yyyy, myDateTime) = DATEADD(dd, -1, Datepart(dd, GetDate()))
AND (DATEPART(mm, myDateTime) = DATEADD(dd, -1, Datepart(mm, GetDate()))
AND (DATEPART(dd, myDateTime) = DATEADD(dd, -1, Datepart(dd, GetDate())) )
ORDER BY
Starttijd ASC
Though this doesn't return any records. When I only use it on the day part of the myDateTime column then it works (but obviously also returns all other years and months with that specific date).
I also couldn't do it using:
SELECT
*
FROM
qryTouchBoekingen
WHERE
myDateTime = DATEADD(dd, -1, GetDate())
because this give errors on the time.
How about this much simpler version:
cast(myDateTime as date) = cast(dateadd(day, -1, getdate()) as date)
Or, even better:
(myDateTime >= cast(dateadd(day, -1, getdate()) as date) and
myDateTime < cast(getdate() as date)
)
This version is more explicit in its ability to take advantage of an index. (The first will also take advantage of an index on myDateTime, but that is an exception to the rule that functions preclude the use of indexes.)
Try this one.
You should count previous day before making datepart from it
Select * from qryTouchBoekingen
WHERE ( DATEPART(yyyy, myDateTime) = Datepart(dd, DATEADD(dd, -1, GetDate()))
AND (DATEPART(mm, myDateTime) = Datepart(mm, DATEADD(dd, -1, GetDate()))
AND (DATEPART(dd, myDateTime) = Datepart(dd, DATEADD(dd, -1, GetDate())) )
Order by Starttijd ASC
DOes this work:
Select
*
from
qryTouchBoekingen
WHERE
CAST( myDateTime AS DATE) = CAST(DATEADD(day, -1, GetDate()) AS DATE)
Order by
Starttijd ASC

How to get this condition in where clause of Sql

I have a query which gives me the last month's completed data
select * from Tabl
where datepart(month, completed_date) = DATEPART(month, getDate())-1
and datepart(year, completed_date) = datepart(year, getDate())
But it gives me wrong data when the current date is in january
How can I write the condition to return correct data if the current month is January?
SQL Server's DATEADD function will help you here.
select * from Tabl
where datepart(month, completed_date) = DATEPART(month, DATEADD(MM,-1,getDate()))
and datepart(year, completed_date) = datepart(year, DATEADD(MM,-1,getDate()))
The 'MM' used is just a keyword for Month.
Well, try subtracting one month from the date instead:
select *
from Tabl
where month(completed_date) = month(dateadd(month, -1, getdate()) and
year(completed_date) = year(dateadd(month, -1, getdate());
But, if you have an index on completed_date, it is better to put all the operations on getdate() so the expression is "sargable" (that is, an index can be used):
where completed_date >= cast(dateadd(month, -1, getdate() - day(getdate() + 1) as date) and
completed_date < cast(getdate() - day(getdate())
When you subtract the "day of the month" from the date, you get the last day of the previous month.
select * from Tabl
where
datepart(year, completed_date) * 100 + datepart(month, completed_date)
<
datepart(year, getDate()) * 100 + datepart(month, GetDate())