SUM columns by hour (using DATETIME column) - sql

I have a database that I need to sum 2 values using the datetime column. Example:
Date Offered
4/16/2012 08:00:00 2
4/16/2012 08:30:00 18
4/16/2012 09:00:00 14
4/16/2012 09:30:30 42
I need to sum the values of 08:00:00 with 08:30:00 (total: 20) and 09:00:00 with 09:30:00 (total: 56) and so on.

This should work for you
select datepart(hour,myDate), SUM(Offered)
from myTable
group by
datepart(hour,myDate),
dateadd(d, 0, datediff(d, 0, myDate))
You need to group by both the hour and the date if you want it summed by individual day, otherwise you'll include other days (IE April 15 etc...)

Your pseudo code
Select HOUR(date), sum(offered) as sumO
FROM YourTable
Group By Hour(date)
Hour(date) would need to be altered to the correct syntax for the database you're working with.

SELECT [Hour] = DATEPART(HOUR, [Date]), Offered = SUM(Offered)
FROM dbo.table_name
WHERE [Date] >= '20120416'
AND [Date] < '20120417'
GROUP BY DATEPART(HOUR, [Date])
ORDER BY [Hour];

Use a DatePart function.
Syntax depends on your database
Select DatePart("year", Date), Sum(Offered)
From table1
Group By DatePart("year", Date)

Related

SQL server calculate total of minutes per day

I am trying to calculated the time of an intervention per day:
Imagine the following scenario:
Intervention Start
Intervention End
Total time
01/09/2021 10:00:00
01/09/2021 12:00:00
01/09/2021 02:00:00
02/09/2021 23:30:00
03/09/2021 01:30:00
02/09/2021 00:30:00 and 03/09/2021 01:30:00
What is the best way to achieve this?
We can have more than 1 day of difference between interventions, also.
You can use a difference as milliseconds, seconds, minutes ... depending on your precision requirements. ie:
select interventionStart, interventionEnd, datediff(seconds, interventionStart, interventionEnd) totalTime
from myTable;
You could then convert seconds to your desire of display (ie: in .Net you might use TimeSpan's ToString() method.)
EDIT: If you absolutely need times "per date", then you could do this:
WITH
adjusted AS (
SELECT
interventionStart, interventionEnd
FROM myTable
WHERE CAST(interventionStart AS DATE)=CAST(interventionEnd AS DATE)
UNION ALL
SELECT
interventionStart, CAST(interventionEnd AS DATE) interventionEnd
FROM myTable
WHERE CAST(interventionStart AS DATE)!=CAST(interventionEnd AS DATE)
UNION ALL
SELECT
CAST(interventionEnd AS DATE) interventionStart, interventionEnd
FROM myTable
WHERE CAST(interventionStart AS DATE)!=CAST(interventionEnd AS DATE)
)
SELECT
adjusted.interventionStart
, adjusted.interventionEnd
, DATEDIFF(SECOND, interventionStart, interventionEnd) totalTime
, DATEADD(
SECOND, DATEDIFF(SECOND, interventionStart, interventionEnd)
, CAST(CAST(adjusted.interventionStart AS DATE) AS DATETIME)
) ifYouWish
FROM adjusted;
DbFiddle demo is here
You could try this if it answers your question.
SELECT Intervention_Start, Intervention_End, AGE(Intervention_Start,
Intervention_End) AS Total_Time from <table_name>;
Time in seconds by date. You can covert it to minutes, hours at will
select cast(c.d as date) dt, datediff(second, case when c.d > m.InterventionStart then c.d else m.InterventionStart end,
case when c2.d < m.InterventionEnd then c2.d else m.InterventionEnd end) seconds
from calendar c -- contains d = datetime of the start of the day, 2021-09-01 00:00:00 etc
-- next day
cross apply (values (dateadd(day, 1, c.d))) c2(d)
left join mytable m on c.d < m.InterventionEnd and m.InterventionStart < c2.d
db-fiddle

SQL query SELECT time intervals

I'm trying to SELECT all the rows from a SQL database which are between an hour interval, for every day.
The datetime column is called "Dt" and has the following datetime format: 2019-10-17 16:03:43
I'd like to extract all the rows from this table where the Dt was between 22:00:00 and 02:00:00, for everyday.
SELECT *
FROM MY_TABLE
WHERE "Dt" BETWEEN '*-*- 22:00:00' AND '*-*- 02:00:00';
where * should be any...
Thanks for your support!
EDIT: I forgot to mention: I'm using the integrated SQL interpreter from DB Browser for SQLite
You need to extract the time part of the date and compare that it is within the range. Since midnight is between 22 and 2, you will need to split it to two comparisons, time between 22 and 0 and between 0 and 2.
To see how to extract the time take a look at this question.
With Postgres, assuming dt is defined as timestamp you can do the following:
SELECT *
FROM MY_TABLE
WHERE "Dt" BETWEEN "Dt"::date + time '22:00:00' and ("Dt"::date + 1) + time '02:00:00'
Or if you want to exclude timestamps at precisely 02:00:00
SELECT *
FROM MY_TABLE
WHERE "Dt" >= "Dt"::date + time '22:00:00'
and "Dt" < ("Dt"::date + 1) + time '02:00:00'
select DT_time from (
select cast (substr(to_char(Dt,'dd-mm-yyyy HH:MM:SS'),12,2) as integer ) as DT_time from MY_TABLE )
where DT_time between 2 and 22;
between 22:00:00 and 02:00:00
means:
SELECT *
FROM MY_TABLE
WHERE
substr(Dt, 12) BETWEEN '22:00:00' AND '23:59:59'
OR
substr(Dt, 12) BETWEEN '00:00:00' AND '02:00:00'
This will work ::
SELECT *
FROM MY_TABLE
WHERE DATEPART(HOUR, Dt)>22
AND DATEPART(HOUR, Dt)<2
Update :
SELECT *
FROM MY_TABLE
WHERE Dt Between DATEADD (hour,22,DATEADD(day, DATEDIFF(day, 0, Dt), 0)) AND DATEADD (hour,2,DATEADD(day, DATEDIFF(day, -1, Dt), 0))
SELECT *
FROM MY_TABLE
WHERE DATEPART(HOUR, Dt)>22
OR DATEPART(HOUR, Dt)<2
Above query work for you..
1st one will check only for particular date and consecutive next date along with your time range.
But If you don't care about dates and only looking for time interval in particular hours then 2nd one is for you.
For SQLite :
SELECT *
FROM MY_TABLE
WHERE strftime('%H','Dt')>22
OR strftime('%H','Dt')<2

Count register depending of current date

I have a table who have creation date like:
SELECT [CreationDate] FROM Store.Order
So each register have one datetime like:
2018-03-14 00:00:00.000
2017-04-14 00:00:00.000
2017-06-14 00:00:00.000
I want to know how to COUNT only register of Date equals to current month and year, for example in this case,if I only have one
register in month 03 I just get 1 on count, how can I achieve it? Regards
Here is one option:
SELECT COUNT(*)
FROM Store.Order
WHERE
CONVERT(varchar(7), [CreationDate], 126) = CONVERT(varchar(7), GETDATE(), 126);
Demo
We can convert both the creation date in your table and the current date into yyyy-mm strings, and then check if they be equal.
The most efficient way is to do:
where creationdate >= dateadd(day, 1 - day(getdate(), cast(getdate() as date)) and
creationdate < dateadd(month, 1, dateadd(day, 1 - day(getdate(), cast(getdate() as date)))
Although this looks more complex than other solutions, all the complexity is on getdate() -- meaning that the optimizer can use indexes on creationdate.

Rounding dates to first day of the month

I am using SQL Server 2014 and I am working with a column from one of my tables, which list arrival dates.
It is in the following format:
ArrivalDate
2015-10-17 00:00:00.000
2015-12-03 00:00:00.000
I am writing a query that would pull data from the above table, including the ArrivalDate column. However, I will need to convert the dates so that they become the first day of their respective months.
In other words, my query should output the above example as follows:
2015-10-01 00:00:00.000
2015-12-01 00:00:00.000
I need this so that I can create a relationship with my Date Table in my PowerPivot model.
I've tried this syntax but it is not meeting my requirements:
CONVERT(CHAR(4),[ArrivalDate], 100) + CONVERT(CHAR(4), [ArrivalDate], 120) AS [MTH2]
If, for example, it is 15th of given month then you subtract 14 and cast the result to date:
SELECT ArrivalDate
, CAST(DATEADD(DAY, -DATEPART(DAY, ArrivalDate) + 1, ArrivalDate) AS DATE) AS FirstDay
FROM (VALUES
(CURRENT_TIMESTAMP)
) AS t(ArrivalDate)
ArrivalDate | FirstDay
2019-05-15 09:35:12.050 | 2019-05-01
But my favorite is EOMONTH which requires SQL Server 2012:
SELECT ArrivalDate
, DATEADD(DAY, 1, EOMONTH(ArrivalDate, -1)) AS FirstDay
FROM (VALUES
(CURRENT_TIMESTAMP)
) AS t(ArrivalDate)
ArrivalDate | FirstDay
2019-05-15 09:35:52.657 | 2019-05-01
Use FORMAT to format your date.
DECLARE #date DATETIME = '2015-10-17 00:00:00.000'
SELECT FORMAT(#date, 'yyyy-MM-01 HH:mm:ss.fff')
Or if you don't want time part:
SELECT FORMAT(#date, 'yyyy-MM-01 00:00:00.000')
LiveDemo
Beginning with SQL Server 2012, you can also use DATEFROMPARTS:
SELECT DATEFROMPARTS(YEAR(ArrivalDate), MONTH(ArrivalDate), 1)
FROM my_table
Round date to first of the month:
DATEADD(MONTH, DATEDIFF(MONTH, 0, DateColumn), 0)
Or just simply use the ROUND function -
SELECT ROUND (TO_DATE ('27-OCT-00'),'YEAR')
"New Year" FROM DUAL;
New Year
01-JAN-01

Get average value per day/hour without Group By

In a single table, say I have a log of mileage and timestamps. I want to get the average mileage per day and per hour. I can't use an inherent "Group By" clause because of the date format.
Here is some sample data:
Table: tb_mileage
===============================================
f_mileagetimestamp f_mileage
-----------------------------------------------
2014-08-11 11:13:02.000 50
2014-08-11 16:12:55.000 100
2014-08-11 16:55:00.000 30
2014-08-12 11:12:50.000 80
2014-08-12 16:12:49.000 100
2014-08-13 08:12:46.000 40
2014-08-13 08:45:31.000 100
So, the ideal result set would appear as follows (PER DAY) (note, format of date doesn't matter):
Date Average
------------------------------------------------
08/11/2014 60
08/12/2014 90
08/13/2014 70
The ideal result set would appear as follows (PER HOUR) (note, format of date doesn't matter):
Date Average
------------------------------------------------
08/11/2014 11:00:00 50
08/11/2014 16:00:00 65
08/12/2014 11:00:00 80
08/12/2014 16:00:00 100
08/13/2014 08:00:00 70
Note that the example here is purely theoretical and simplified, and doesn't necessarily reflect the exact criteria necessary for the real-world implementation. This is merely to push my own learning, because all the examples I found to do similar things were hugely complex, making learning difficult.
Try this for the dates version.
select cast(t.f_mileagetimestamp as date) as dt, avg(t.f_mileage) as avg_mileage
from
tb_mileage t
group by cast(t.f_mileagetimestamp as date)
order by cast(t.f_mileagetimestamp as date) asc;
For the hours version, you can use this.
select t2.dt, avg(t2.f_mileage) as avg_mileage
from
(
select substring(CONVERT(nvarchar(100), t1.f_mileagetimestamp, 121), 1, 13) + ':00' as dt, t1.f_mileage
from
tb_mileage t1
) t2
group by t2.dt
order by t2.dt asc;
I think this should work for the "day" version:
select cast(f_mileagetimestamp as date), avg(f_mileage)
from tb_mileage
group by cast(f_mileagetimestamp as date)
order by cast(f_mileagetimestamp as date);
For the hour, I would just use the function:
select cast(f_mileagetimestamp as date), datepart(hour, f_mileagetimestamp), avg(f_mileage)
from tb_mileage
group by cast(f_mileagetimestamp as date), datepart(hour, f_mileagetimestamp)
order by cast(f_mileagetimestamp as date), datepart(hour, f_mileagetimestamp);