SQL Server Query for average value over a date period - sql

DECLARE #SampleOrderTable TABLE
(
pkPersonID INT,
OrderDate DATETIME,
Amount NUMERIC(18, 6)
)
INSERT INTO #SampleOrderTable (pkPersonID, OrderDate, Amount)
VALUES (1, '12/10/2019', '762.84'),
(2, '11/10/2019', '886.32'),
(3, '11/9/2019', '10245.00')
How do I select the the last 4 days prior to OrderDate and the average Amount over that period?
So result data would be:
pkPersonID Date Amount
------------------------------------
1 '12/7/2019' 190.71
1 '12/8/2019' 190.71
1 '12/9/2019' 190.71
1 '12/10/2019' 190.71
2 '12/7/2019' 221.58
2 '12/8/2019' 221.58
2 '12/9/2019' 221.58
2 '12/10/2019' 221.58
3 '11/6/2019' 2561.25
3 '11/7/2019' 2561.25
3 '11/8/2019' 2561.25
3 '11/9/2019' 2561.25

You may try with the following approach, using DATEADD(), windowed COUNT() and VALUES() table value constructor:
Table:
DECLARE #SampleOrderTable TABLE (
pkPersonID INT,
OrderDate DATETIME,
Amount NUMERIC(18, 6)
)
INSERT INTO #SampleOrderTable (pkPersonID, OrderDate, Amount)
VALUES (1, '20191210', '762.84'),
(2, '20191210', '886.32'),
(3, '20191109', '10245.00')
Statement:
SELECT
t.pkPersonID,
DATEADD(day, -v.Day, t.OrderDate) AS [Date],
CONVERT(numeric(18, 6), Amount / COUNT(Amount) OVER (PARTITION BY t.pkPersonID)) AS Amount
FROM #SampleOrderTable t
CROSS APPLY (VALUES (0), (1), (2), (3)) v(Day)
ORDER BY t.pkPersonID, [Date]
Result:
pkPersonID Date Amount
1 07/12/2019 00:00:00 190.710000
1 08/12/2019 00:00:00 190.710000
1 09/12/2019 00:00:00 190.710000
1 10/12/2019 00:00:00 190.710000
2 07/12/2019 00:00:00 221.580000
2 08/12/2019 00:00:00 221.580000
2 09/12/2019 00:00:00 221.580000
2 10/12/2019 00:00:00 221.580000
3 06/11/2019 00:00:00 2561.250000
3 07/11/2019 00:00:00 2561.250000
3 08/11/2019 00:00:00 2561.250000
3 09/11/2019 00:00:00 2561.250000

You can use sql functions like AVG, DATEADD and GETDATE.
SELECT AVG(Amount) as AverageAmount
FROM #SampleOrderTable
WHERE OrderDate >= DATEADD(DAY, -4, GETDATE())

DECLARE #SampleOrderTable TABLE (
pkPersonID INT,
OrderDate DATETIME,
Amount NUMERIC(18, 6)
);
INSERT INTO #SampleOrderTable
(pkPersonID, OrderDate, Amount)
VALUES
(1, '12/20/2019', 762.84),
(2, '12/20/2019', 886.32),
(3, '12/20/2019', 10245.00),
(4, '12/19/2019', 50.00),
(5, '12/19/2019', 100.00),
(6, '09/01/2019', 200.00),
(7, '09/01/2019', 300.00),
(8, '12/15/2019', 400.00),
(9, '12/15/2019', 500.00),
(10, '09/02/2019', 150.00),
(11, '09/02/2019', 1100.00),
(12, '09/02/2019', 1200.00),
(13, '09/02/2019', 1300.00),
(14, '09/02/2019', 1400.00),
(15, '09/02/2019', 1500.00);
SELECT OrderDate,AVG(Amount) AS Average_Value
FROM #SampleOrderTable
WHERE DATEDIFF(DAY, CAST(OrderDate AS DATETIME), CAST(GETDATE() AS Datetime)) <= 4
GROUP BY OrderDate;

Related

Function that returns MAX OR MIN dates based on ID count

I have a task in SQL Server where I need to return the RESULT_DATE column using ID, PRODUCT_ID and DATE columns. Task criteria:
If DATE column is filled once for each PRODUCT_ID then I need to return the only date (like for PRODUCT_ID 1 and 3). Let`s say its MIN date.
If DATE column is filled more than one time (like for PRODUCT_ID 2) then I need to return the next filled DATE row.
Data:
CREATE TABLE #temp (
ID INT,
PRODUCT_ID INT,
[DATE] DATETIME
)
INSERT #temp (ID, PRODUCT_ID, DATE) VALUES
(1, 1, '2008-04-24 00:00:00.000'),
(2, 1, NULL),
(3, 2, '2015-12-09 00:00:00.000'),
(4, 2, NULL),
(5, 2, NULL),
(6, 2, '2022-01-01 13:06:45.253'),
(7, 2, NULL),
(8, 2, '2022-01-19 13:06:45.253'),
(9, 3, '2018-04-25 00:00:00.000'),
(10,3, NULL),
(11,3, NULL)
ID
PRODUCT_ID
DATE
RESULT_DATE
1
1
2008-04-24 00:00:00.000
2008-04-24 00:00:00.000
2
1
NULL
2008-04-24 00:00:00.000
3
2
2015-12-09 00:00:00.000
2022-01-01 13:06:45.253
4
2
NULL
2022-01-01 13:06:45.253
5
2
NULL
2022-01-01 13:06:45.253
6
2
2022-01-01 13:06:45.253
2022-01-19 13:06:45.253
7
2
NULL
2022-01-19 13:06:45.253
8
2
2022-01-19 13:06:45.253
2022-01-19 13:06:45.253
9
3
2018-04-25 00:00:00.000
2018-04-25 00:00:00.000
10
3
NULL
2018-04-25 00:00:00.000
11
3
NULL
2018-04-25 00:00:00.000
I have tried different techniques, for example using LEAD and LAG SQL function combinations. The latest script: (However, still not working)
SELECT
COALESCE(DATE,
CAST(
SUBSTRING(
MAX(CAST(DATE AS BINARY(4)) + CAST(DATE AS BINARY(4))) OVER ( PARTITION BY PRODUCT_ID ORDER BY DATE ROWS UNBOUNDED PRECEDING)
,5,4)
AS INT)
) AS RESULT_DATE,
*
FROM TABLE
You can use a CTE, Select all rows with a non-NULL Date giving each a row_number, then use a second CTE to fetch all rows from the first CTE equivalent to the date with the largest row number per product_id that is less than 3. Finally join this CTE to the original table to supply the 2nd Date to each row:
Set Up
CREATE TABLE #temp (
ID INT,
PRODUCT_ID INT,
MyDATE DATETIME
)
INSERT #temp (ID, PRODUCT_ID, MyDate)
VALUES
(1, 1, '2008-04-24 00:00:00.000'),
(2, 1, NULL),
(3, 2, '2015-12-09 00:00:00.000'),
(4, 2, NULL),
(5, 2, NULL),
(6, 2, '2022-01-01 13:06:45.253'),
(7, 2, NULL),
(8, 2, '2022-01-19 13:06:45.253'),
(9, 3, '2018-04-25 00:00:00.000'),
(10,3, NULL),
(11,3, NULL);
Query:
;WITH CTE
AS
(
SELECT ID, Product_ID, MyDate,
ROW_NUMBER() OVER (PARTITION BY Product_ID ORDER BY Id) AS rn
from #temp
WHERE MyDate IS NOT NULL
),
CTE2
AS
(
SELECT *
FROM CTE C1
WHERE C1.rn < 3
AND
C1.rn =
(SELECT MAX(rn) FROM CTE WHERE Product_Id = C1.Product_Id AND rn<3)
)
SELECT T.Id, T.Product_Id, T.MyDate, C.MyDate As Result_date
FROM #temp T
INNER JOIN CTE2 C
ON T.Product_Id = C.Product_Id
ORDER BY T.Id;
Results:
Id Product_Id MyDate Result_Date
1 1 2008-04-24 00:00:00.000 2008-04-24 00:00:00.000
2 1 NULL 2008-04-24 00:00:00.000
3 2 2015-12-09 00:00:00.000 2022-01-01 13:06:45.253
4 2 NULL 2022-01-01 13:06:45.253
5 2 NULL 2022-01-01 13:06:45.253
6 2 2022-01-01 13:06:45.253 2022-01-01 13:06:45.253
7 2 NULL 2022-01-01 13:06:45.253
8 2 2022-01-19 13:06:45.253 2022-01-01 13:06:45.253
9 3 2018-04-25 00:00:00.000 2018-04-25 00:00:00.000
10 3 NULL 2018-04-25 00:00:00.000
11 3 NULL 2018-04-25 00:00:00.000

SQL Server Query to pull/updating the missing data from Previous months value

I have a two tables table Rev and Table Cost from both these tables are common column is Product ID and Tdate (Month/Year) for join.
from Table Rev I need to pull the cost from Table Cost table, however, if the cost is not found for the particular month then it should check for the previous month and bring that cost for that product. Like that it should check till last 6 months (looping) if the cost is not available and get the latest cost whichever is available for latest 6 months from that date.
However I am not able to get any idea how to solve it, Please help.
REV
Product ID Transaction Date Output should be
101 3/5/2018 16.8
101 3/24/2018 16.8
101 4/10/2018 16.8
101 5/30/2018 7.6
101 6/25/2018 14.3
102 1/1/2019 30.11
102 2/4/2019 30.11
102 2/11/2019 30.11
103 2/17/2019 6.62
103 2/25/2019 6.62
103 3/24/2019 6.62
103 3/30/2019 6.62
for the REV table I need to bring the cost based on PROD ID and Month/Year Match, if not available it should check for last 6 months backdate and bring the cost latest available month.
Cost
Product ID PCR Period Cost
101 Jan-18 16.8
101 May-18 7.6
101 Jun-18 14.3
101 Jul-18 301.88
101 Aug-18 6.62
101 Nov-18 0.01
102 Dec-18 6.62
102 May-18 47.95
102 Jun-18 79.8
102 Jul-18 3.49
102 Jan-19 30.11
103 Mar-19 102.11
Let me know if you need any futher details
This should be close to what you're after
select r.id, r.td, (
select top 1 c.cost from cost c
where c.id = r.id
and datediff(day, CAST('01-' + c.td AS datetime), r.td) >= 0
order by CAST('01-' + c.td AS datetime) desc
) as cost
from rev r
EXAMPLE SCRIPT:
declare #REV table (id int, trandate datetime)
insert into #REV (id, trandate) values (101, '3/5/2018')
insert into #REV (id, trandate) values (101, '3/24/2018')
insert into #REV (id, trandate) values (101, '4/10/2018')
insert into #REV (id, trandate) values (101, '5/30/2018')
insert into #REV (id, trandate) values (101, '6/25/2018')
insert into #REV (id, trandate) values (102, '1/1/2019')
insert into #REV (id, trandate) values (102, '2/4/2019')
insert into #REV (id, trandate) values (102, '2/11/2019')
insert into #REV (id, trandate) values (103, '2/17/2019')
insert into #REV (id, trandate) values (103, '2/25/2019')
insert into #REV (id, trandate) values (103, '3/24/2019')
insert into #REV (id, trandate) values (103, '3/30/2019')
declare #COST table (id int, pcr varchar(20), cost float)
insert into #COST (id, pcr, cost) values (101, 'Jan-18', 16.8)
insert into #COST (id, pcr, cost) values (101, 'May-18', 7.6)
insert into #COST (id, pcr, cost) values (101, 'Jun-18', 14.3)
insert into #COST (id, pcr, cost) values (101, 'Jul-18', 301.88)
insert into #COST (id, pcr, cost) values (101, 'Aug-18', 6.62)
insert into #COST (id, pcr, cost) values (101, 'Nov-18', 0.01)
insert into #COST (id, pcr, cost) values (102, 'Dec-18', 6.62)
insert into #COST (id, pcr, cost) values (102, 'May-18', 47.95)
insert into #COST (id, pcr, cost) values (102, 'Jun-18', 79.8)
insert into #COST (id, pcr, cost) values (102, 'Jul-18', 3.49)
insert into #COST (id, pcr, cost) values (102, 'Jan-19', 30.11)
insert into #COST (id, pcr, cost) values (103, 'Mar-19', 102.11)
select r.id, r.trandate, (
select top 1 c.cost from #cost c
where c.id = r.id
and datediff(day, CAST('01-' + c.pcr AS datetime), r.trandate) >= 0
order by CAST('01-' + c.pcr AS datetime) desc
) as cost
from #rev r
RESULTS:
101 2018-03-05 16.8
101 2018-03-24 16.8
101 2018-04-10 16.8
101 2018-05-30 7.6
101 2018-06-25 14.3
102 2019-01-01 30.11
102 2019-02-04 30.11
102 2019-02-11 30.11
103 2019-02-17 NULL
103 2019-02-25 NULL
103 2019-03-24 102.11
103 2019-03-30 102.11
SELECT A.PRODUCT_ID
,A.TRANSACTION_DATE
,(
SELECT TOP 1 X.COST
FROM COST X
WHERE X.PRODUCT_ID = A.PRODUCT_ID
AND X.PCR_PERIOD < = A.TRANSACTION_DATE
AND X.PCR_PERIOD > DATEADD(MONTH,-6,A.TRANSACTION_DATE)
ORDER BY X.PCR_PERIOD DESC
) AS COST
FROM REV A
Written using Outer Apply and assuming PCR Period is a date:
SELECT REV.[Product ID], REV.[Transaction Date], LastCost.[Cost]
FROM REV
OUTER APPLY
(
SELECT TOP 1 Cost.Cost
FROM Cost
WHERE Cost.[Product ID]= REV.[Product ID]
AND Cost.[PCR Period] BETWEEN dateadd(month,-6,REV.[Transaction Date]) and REV.[Transaction Date]
ORDER BY Cost.[PCR Period] DESC
) AS LastCost

Finding duplicate records in a specific date range

I have a table where I have 4 columns
Serial(nvarchar), SID(nvarchar), DateCreated(Date), CID(unique and int)
I want to find the records where there is duplicate serial and SID and where the 2 duplicate serial fall between date range of 180 days.
please help
Sample Data
Serial SID DateCreated CID
02302-25-0036 HONMD01 2017-05-01 00:00:00.000 1
02302-25-0036 HONMD01 2017-05-01 00:00:00.000 3
0264607 HONMD01 2017-05-01 00:00:00.000 65
0264607 HONMD01 2016-05-01 00:00:00.000 45
03118-09-0366 PRIVA00 2016-05-20 00:00:00.000 34
03118-09-0366 PRIVA00 2016-05-20 00:00:00.000 87
0969130 140439 2017-05-09 00:00:00.000 32
0969130 140439 2017-05-09 00:00:00.000 23
1049567 INIIL00 2017-04-12 00:00:00.000 76
create table #Test (Serial nvarchar(20), [SID] nvarchar(10), DateCreated datetime, CID int)
Insert into #Test values ('02302-25-0036', 'HONMD01', '2017-05-01 00:00:00.000', 1)
, ('02302-25-0036', 'HONMD01', '2017-05-01 00:00:00.000', 3)
, ('0264607', 'HONMD01', '2017-05-01 00:00:00.000', 65)
, ('0264607', 'HONMD01', '2016-05-01 00:00:00.000', 45)
, ('03118-09-0366', 'PRIVA00', '2016-05-20 00:00:00.000', 34)
, ('03118-09-0366', 'PRIVA00', '2016-05-20 00:00:00.000', 87)
, ('0969130', '140439', '2017-05-09 00:00:00.000', 32)
, ('0969130', '140439', '2017-05-09 00:00:00.000', 23)
, ('1049567', 'INIIL00', '2017-04-12 00:00:00.000', 76)
select distinct a.*
from
(
select t.*
from #Test t
inner join (
Select Serial, [SID]
from #Test
group by Serial, [SID]
Having count(*)>=2
) d on d.Serial = t.Serial and t.SID= t.SID
) a
full outer join
(
select t.*
from #Test t
inner join (
Select Serial, [SID]
from #Test
group by Serial, [SID]
Having count(*)>=2
) d on d.Serial = t.Serial and t.SID= t.SID
) b on a.Serial = b.Serial and a.SID= b.SID
where datediff(d,a.DateCreated, b.DateCreated)<180
Try to do this:
with cte as (
select
serial,
sid,
dateCreated,
cid,
coalesce(max(dateCreated) over(partition by serial, sid order by cid, dateCreated asc rows between unbounded preceding and 1 preceding), '1900-01-01') as last,
coalesce(min(dateCreated) over(partition by serial, sid order by cid, dateCreated asc rows between 1 following and unbounded following), '5999-01-01') as next
from table_name
)
select *
from cte
where
datediff(day, last, dateCreated) >= 180
and datediff(day, dateCreated, next) >= 180
This was a challenging question ! I have left final output with *(PreviousDate, rno) for easy understanding. Here is my way to solve :
Create table #t(Serial nvarchar(100),SID nvarchar(100),DateCreated date,CID int)
Insert into #t values
('02302-25-0036', 'HONMD01', '2017-05-01 00:00:00.000', 1),
('02302-25-0036', 'HONMD01', '2017-05-01 00:00:00.000', 3),
('0264607', 'HONMD01', '2017-05-01 00:00:00.000', 65),
('0264607', 'HONMD01', '2016-05-01 00:00:00.000', 45),
('03118-09-0366', 'PRIVA00', '2016-05-20 00:00:00.000', 34),
('03118-09-0366', 'PRIVA00', '2016-05-20 00:00:00.000', 87),
('0969130', '140439', '2017-05-09 00:00:00.000', 32),
('0969130', '140439', '2017-05-09 00:00:00.000', 23),
('1049567', 'INIIL00', '2017-04-12 00:00:00.000', 76)
Select iq2.*
FROM
(Select iq.Serial, iq.SID, iq.DateCreated, iq.CID, iq.PreviousDate,
ROW_NUMBER() OVER (PARTITION BY iq.Serial,iq.SID, CASE WHEN DATEDIFF(day, iq.DateCreated, iq.PreviousDate) <= 180 THEN 1 ELSE 0 END
ORDER BY Serial,SID) rno
FROM
(select Serial,SID,DateCreated,CID,
MAX(DateCreated) OVER (PARTITION BY Serial,SID ORDER BY Serial,SID) maxDate,
DATEADD(day,-180,MAX(DateCreated) OVER (PARTITION BY Serial,SID ORDER BY Serial,SID)) PreviousDate
from #t
)iq
)iq2
where iq2.rno <> 1
output :
Serial SID DateCreated CID PreviousDate rno
---------- ------- ---------- ---- ----------- ----
02302-25-0036 HONMD01 2017-05-01 3 2016-11-02 2
03118-09-0366 PRIVA00 2016-05-20 87 2015-11-22 2
0969130 140439 2017-05-09 23 2016-11-10 2
PS : PreviousDate is MAX PreviousDate

T-SQL: Conditional NULL removal

I need to select only the Room_IDs that have no instances where the Status is NULL.
For example here :
TABLE_A
Room_Id Status Inspection_Date
-----------------------------------
1 NULL 5/15/2015
2 occupied 5/21/2015
2 NULL 1/19/2016
1 occupied 12/16/2015
4 NULL 3/25/2016
3 vacant 8/27/2015
1 vacant 4/17/2016
3 vacant 12/12/2015
3 vacant 3/22/2016
4 vacant 2/2/2015
4 vacant 3/24/2015
My result should look like this:
Room_Id Status Inspection_Date
-----------------------------------
3 vacant 8/27/2015
3 vacant 12/12/2015
3 vacant 3/22/2016
Because Room_ID '3' has no instances where the Status is NULL
Quick example of how to do it:
DECLARE #tTable TABLE(
Room_Id INT,
Status VARCHAR(20),
Inspection_Date DATETIME)
INSERT INTO #tTable VALUES
(1, NULL, '5/15/2015'),
(1,NULL, '5/15/2015'),
(2,'occupied', '5/21/2015'),
(2,NULL, '1/19/2016'),
(1,'occupied', '12/16/2015'),
(4,NULL, '3/25/2016'),
(3,'vacant', '8/27/2015'),
(1,'vacant', '4/17/2016'),
(3,'vacant', '12/12/2015'),
(3,'vacant', '3/22/2016'),
(4,'vacant', '2/2/2015'),
(4,'vacant', '3/24/2015')
SELECT * FROM #tTable T1
WHERE Room_Id NOT IN (SELECT Room_ID FROM #tTable WHERE Status IS NULL)
Gives :
Room_Id | Status | Inspection_Date |
-------------------------------------------------
3 | vacant | 2015-08-27 00:00:00.000
3 | vacant | 2015-12-12 00:00:00.000
3 | vacant | 2016-03-22 00:00:00.000
Try this out:
SELECT *
FROM Table1
WHERE Room_ID NOT IN
(
SELECT DISTINCT Room_ID
FROM Table1
WHERE Status IS NULL
)
The sub query returns a list of unique room id's that, at one time or another, had a NULL status. The outer query looks at that list, and says "Return * where the room_ID IS NOT one those in the subquery.
If you want to try it in SQL Fiddle, here is the Schema:
CREATE TABLE Table1
(Room_ID int, Status varchar(8), Inspection_Date datetime)
;
INSERT INTO Table1
(Room_ID, Status, Inspection_Date)
VALUES
(1, NULL, '2015-05-15 00:00:00'),
(2, 'occupied', '2015-05-21 00:00:00'),
(2, NULL, '2016-01-19 00:00:00'),
(1, 'occupied', '2015-12-16 00:00:00'),
(4, NULL, '2016-03-25 00:00:00'),
(4, 'vacant', '2015-08-27 00:00:00'),
(1, 'vacant', '2016-04-17 00:00:00'),
(3, 'vacant', '2015-12-12 00:00:00'),
(3, 'vacant', '2016-03-22 00:00:00'),
(4, 'vacant', '2015-02-02 00:00:00'),
(4, 'vacant', '2015-03-24 00:00:00'),
(2, NULL, '2015-05-22 00:00:00')
;
As alternative to Hashman, I just prefer to use not exists over not in for these types of queries.
Creating some test data
Note that I just kept the same date for everything since it's not imperative to the question.
create table #table_a (
Room_Id int,
Status varchar(32),
Inspection_Date date);
insert #table_a (Room_Id, Status, Inspection_Date)
values
(1, null, getdate()),
(2, 'occupied', getdate()),
(2, null, getdate()),
(1, 'occupied', getdate()),
(4, null, getdate()),
(3, 'vacant', getdate()),
(1, 'vacant', getdate()),
(3, 'vacant', getdate()),
(3, 'vacant', getdate()),
(4, 'vacant', getdate()),
(4, 'vacant', getdate());
The query
select *
from #table_a t1
where not exists (
select *
from #table_a t2
where t1.Room_Id = t2.Room_Id
and Status is null);
The results
Room_Id Status Inspection_Date
----------- -------------------------------- ---------------
3 vacant 2016-06-17
3 vacant 2016-06-17
3 vacant 2016-06-17
You can use CTE and NOT EXIST like below code
WITH bt
AS ( SELECT RoomId ,
Status,
Inspection_Date
FROM dbo.Table_1
)
SELECT *
FROM bt AS a
WHERE NOT EXISTS ( SELECT 1
FROM bt
WHERE bt.RoomId = a.RoomId
AND bt.Status IS NULL );

Return records with counts for the last 24 hours

I am trying to get records from the last 24 hours, grouped by hour with counts in SQL Server?
I have sample data like:
ID Dat
1 2015-01-19 10:29:00.000
2 2015-01-19 11:29:00.000
3 2015-01-19 11:29:00.000
4 2015-01-19 11:29:00.000
5 2015-01-19 12:29:00.000
6 2015-01-19 12:29:00.000
7 2015-01-19 12:29:00.000
8 2015-01-19 12:29:00.000
9 2015-01-17 13:29:00.000
10 2015-01-17 13:29:00.000
11 2015-01-17 13:29:00.000
12 2015-01-17 13:29:00.000
13 2015-01-17 13:29:00.000
14 2015-01-17 13:29:00.000
15 2015-01-17 14:29:00.000
17 2015-01-17 15:29:00.000
18 2015-01-17 15:29:00.000
19 2015-01-17 16:29:00.000
20 2015-01-17 16:29:00.000
21 2015-01-15 16:29:00.000
22 2015-01-15 17:29:00.000
23 2015-01-15 18:29:00.000
24 2015-01-15 18:29:00.000
25 2015-01-15 18:29:00.000
26 2015-01-15 18:29:00.000
27 2015-01-15 18:29:00.000
28 2015-01-15 18:29:00.000
29 2015-01-15 19:29:00.000
30 2015-01-10 20:29:00.000
Now suppose current date time is 2015-01-19 12:30:00.000, my desired output would be:
Date Count
2015-01-19 12:00:00.000 4
2015-01-19 11:00:00.000 3
2015-01-19 10:00:00.000 1
2015-01-19 09:00:00.000 0
2015-01-19 08:00:00.000 0
2015-01-19 07:00:00.000 0
2015-01-19 06:00:00.000 0
2015-01-19 05:00:00.000 4
and so on...
So the count is based on number of records that fall in to each hour.
You can round your values to the nearest hour and then simply GROUP and COUNT:
SQL Fiddle Demo
MS SQL Server Schema Setup:
CREATE TABLE DateTable
([ID] int, [Date] datetime)
;
INSERT INTO DateTable
([ID], [Date])
VALUES
(1, '2015-01-19 10:29:00'),
(2, '2015-01-19 11:29:00'),
(3, '2015-01-19 11:29:00'),
(4, '2015-01-19 11:29:00'),
(5, '2015-01-19 12:29:00'),
(6, '2015-01-19 12:29:00'),
(7, '2015-01-19 12:29:00'),
(8, '2015-01-19 12:29:00'),
(9, '2015-01-17 13:29:00'),
(10, '2015-01-17 13:29:00'),
(11, '2015-01-17 13:29:00'),
(12, '2015-01-17 13:29:00'),
(13, '2015-01-17 13:29:00'),
(14, '2015-01-17 13:29:00'),
(15, '2015-01-17 14:29:00'),
(17, '2015-01-17 15:29:00'),
(18, '2015-01-17 15:29:00'),
(19, '2015-01-17 16:29:00'),
(20, '2015-01-17 16:29:00'),
(21, '2015-01-15 16:29:00'),
(22, '2015-01-15 17:29:00'),
(23, '2015-01-15 18:29:00'),
(24, '2015-01-15 18:29:00'),
(25, '2015-01-15 18:29:00'),
(26, '2015-01-15 18:29:00'),
(27, '2015-01-15 18:29:00'),
(28, '2015-01-15 18:29:00'),
(29, '2015-01-15 19:29:00'),
(30, '2015-01-10 20:29:00')
;
Query to return aggregated data:
SELECT DATEADD(HOUR, DATEDIFF(HOUR, 0, [DATE]), 0) As [DateValue],
COUNT(1) AS [COUNT]
FROM DateTable
WHERE [DATE] >= DATEADD(day, -1, GETDATE())
GROUP BY DATEADD(HOUR, DATEDIFF(HOUR, 0, [DATE]), 0)
ORDER BY 1
Results:
| DATEVALUE | COUNT |
|--------------------------------|-------|
| January, 19 2015 10:00:00+0000 | 1 |
| January, 19 2015 11:00:00+0000 | 3 |
| January, 19 2015 12:00:00+0000 | 4 |
This is using GETDATE() to return the current date time value and taking the last 24 hours from the point. The query above uses the value returned from the below for the WHERE clause:
SELECT DATEADD(day, -1, GETDATE())
You can replace the filter value in the WHERE clause with a variable if required.
Try this, it will also count the hours without data:
DECLARE #t table(ID int, Date datetime)
INSERT #t values
(1,'2015-01-19 10:29:00.000'), (2,'2015-01-19 11:29:00.000'),
(3,'2015-01-19 11:29:00.000'), (4,'2015-01-19 11:29:00.000'),
(5,'2015-01-19 12:29:00.000'), (6,'2015-01-19 12:29:00.000'),
(7,'2015-01-19 12:29:00.000'), (8,'2015-01-19 12:29:00.000'),
(9,'2015-01-17 13:29:00.000'), (10,'2015-01-17 13:29:00.000'),
(11,'2015-01-17 13:29:00.000'),(12,'2015-01-17 13:29:00.000'),
(13,'2015-01-17 13:29:00.000'),(14,'2015-01-17 13:29:00.000'),
(15,'2015-01-17 14:29:00.000'),(17,'2015-01-17 15:29:00.000'),
(18,'2015-01-17 15:29:00.000'),(19,'2015-01-17 16:29:00.000'),
(20,'2015-01-17 16:29:00.000'),(21,'2015-01-15 16:29:00.000'),
(22,'2015-01-15 17:29:00.000'),(23,'2015-01-15 18:29:00.000'),
(24,'2015-01-15 18:29:00.000'),(25,'2015-01-15 18:29:00.000'),
(26,'2015-01-15 18:29:00.000'),(27,'2015-01-15 18:29:00.000'),
(28,'2015-01-15 18:29:00.000'),(29,'2015-01-15 19:29:00.000'),
(30,'2015-01-10 20:29:00.000')
DECLARE #yourdate datetime = '2015-01-19T12:30:00.000'
;WITH CTE AS
(
SELECT dateadd(hh, datediff(hh, 0, #yourdate), 0) Date
UNION ALL
SELECT dateadd(hh, -1, Date)
FROM CTE
WHERE Date + 1 > #yourdate
)
SELECT CTE.Date, count(t.id) count
FROM CTE
LEFT JOIN #t t
ON CTE.Date <= t.Date
and dateadd(hh, 1, CTE.Date) > t.Date
GROUP BY CTE.Date
ORDER BY CTE.Date DESC
Result:
Date Count
2015-01-19 12:00:00.000 4
2015-01-19 11:00:00.000 3
2015-01-19 10:00:00.000 1
2015-01-19 09:00:00.000 0
2015-01-19 08:00:00.000 0
.....
create table #temptable
(
ID int ,
Date datetime
)
go
insert into #temptable (id, Date)
select 1 , '2014-01-19 10:29:00.000' union all
select 2 , '2014-01-19 11:29:00.000' union all
select 3 , '2014-01-19 11:29:00.000' union all
select 4 , '2014-01-19 11:29:00.000' union all
select 5 , '2014-01-19 09:29:00.000' union all
select 6 , '2014-01-19 08:29:00.000' union all
select 7 , '2014-01-19 03:29:00.000'
SELECT CAST(Date as date) AS ForDate,
DATEPART(hour,Date) AS OnHour,
COUNT(*) AS Totals
FROM #temptable
GROUP BY CAST(Date as date),
DATEPART(hour,Date)
SQL Server Group by Count of DateTime Per Hour?
It may helps you
declare #t table(t datetime)
insert into #t values(getdate()),(getdate())
SELECT cast(cast(getdate() as date) as datetime)+cast(datepart(hour,getdate()) as float)/24, count(*)
from #t
group by cast(cast(getdate() as date) as datetime)+cast(datepart(hour,getdate()) as float)/24
try this
For SQL SERVER
select CAST( MyDateColumn as DATE) ,DATEPART(HOUR, MyDateColumn),COUNT(*)
from MyTable
GROUP BY CAST( MyDateColumn as DATE) ,DATEPART(HOUR, MyDateColumn)