How can I group data on the basis of date and hour in ms-sql? - sql-server

I have following data in my table activity_count
Activitydate |count
2013-12-20:18:25:45 10
2013-12-20:18:23:40 20
2013-12-20:17:25:45 5
2013-12-20:17:25:45 10
2013-12-20:17:25:45 10
I want to get the total counts for each hour,ie the result should be following
Activitydate |count
2013-12-20:18:00:00 30
2013-12-20:17:00:00 25

If you're using mySQL try below:
SELECT CONCAT(LEFT(DATE(activitydate),10),' ',HOUR(activitydate),':00:00') as DateHour,
SUM(count) as TotalCount
FROM activity_count
GROUP BY DATE(activitydate),HOUR(activitydate)
See my Demo.
However, if MSSQL try this one:
SELECT CAST(CAST(activitydate as DATE) AS nvarchar(15))+' '+CAST(datepart(HOUR,activitydate) as CHAR(2))+':00:00' as DateHour,
SUM([count]) as TotalCount
FROM activity_count
GROUP BY CAST(CAST(activitydate as DATE) AS nvarchar(15)),DATEPART(HOUR, activitydate)
See MSSQL Demo

please try this
select cast(cast(Activitydate as date) as datetime)+cast(datepart(hour,Activitydate),
count(*)
from activity_count
group by cast(cast(Activitydate as date) as datetime)+cast(datepart(hour,Activitydate)

Try HOUR function
select
Activitydate,
count(*) as 'count'
from activity_count
GROUP BY HOUR(Activitydate)

HOUR(time)
HOUR(time)
Returns the hour for time. The range of the return value is 0 to 23 for time-of-day values. However, the range of TIME values actually is much larger, so HOUR can return values greater than 23.

Related

I would like the number '1000' to appear once only and then '0' for the remaining records until the next month appears-maybe a case type statement?

I am using SQL and I would like this number '1000' to appear once per month. I have a record set which has the first of every month appearing multiple times. I would like the number '1000' to appear once only and then '0' for the remaining records until the next month appears. I would like the below please- maybe a case type statement/order parition by? I am using SQL Server 2018 ##SQLSERVER. Please see table below of how i would like the data to appear.
Many Thanks :)
Date
Amount
01/01/2022
1000
01/01/2022
0
01/01/2022
0
01/02/2022
1000
01/02/2022
0
01/02/2022
0
01/03/2022
1000
01/03/2022
0
Solution for your problem:
WITH CT1 AS
(
SELECT *,
ROW_NUMBER() OVER(PARTITION BY CONCAT(MONTH([Date]),YEAR([Date])) ORDER BY [Date]) as rn
FROM your_table
)
SELECT [Date],
CASE WHEN rn = 1 THEN 1000 ELSE 0 END AS Amount
FROM CT1;
Working Example: DB<>Fiddle Link
Given just a list of dates you could use row_number and a conditional expression to arbitrarily assign one row of each month a value of 1000
select *,
Iif(Row_Number() over(partition by Month(date) order by (select null)) = 1, 1000, 0) Amount
from t
order by [date], Amount desc;

How to get results older than 6 months in SQL Server 2014?

I need code that pulls up records of Accounts where last Payment Status was older than 6 months ago. But I'm not quite sure why my DateDiff won't work.
My code so far:
SELECT A.[AccountId]
,[AccountNumber]
,[AccountTypeId]
,[AccountStatusId]
,[CurrentBalance]
,[PaymentStatusID]
,D.Last_Change
FROM [Account] A
INNER JOIN (
SELECT AccountId
,MAX(Created) Last_Change
FROM PaymentStatusHistory
WHERE ToPaymentStatusID IN (1,2,11)
GROUP BY AccountId
) D
ON A.AccountID = D.AccountId
WHERE PaymentStatusID IN (1,2,11)
AND AccountStatusId IN (1,2)
--AND DATEDIFF (DAY, GETDATE(), D.Last_Change) > 180 --Need THIS line corrected.
ORDER BY CurrentBalance DESC, AccountNumber
You seem to have mixed up the starting_date and ending_date of your datediff.
AND DATEDIFF (DAY, D.Last_Change, GETDATE()) > 180
Get_date(), current date, should be after your Last_change date.
If you want a positive number, try reversing the order of the dates in your DATEDIFF.
For example: SELECT DATEDIFF(DAY,GETDATE(),'20170101') returns -250. SELECT DATEDIFF(DAY,'20170101',GETDATE()) returns 250.
I changed the order in the DATEDIFF and it worked.
AND DATEDIFF (DAY, D.Last_Change, GETDATE()) > 180
This line of code worked and gave me the result as needed.

Group by on Postgresql Date Time

Hy. There are employee records in my postgresql database something like
CODE DATE COUNT
"3443" "2009-04-02" 3
"3444" "2009-04-06" 1
"3443" "2009-04-06" 1
"3443" "2009-04-07" 7
I want to use a query "SELECT ALL CODES AND COUNT THEM THAT OCCURRED IN THE MONTH"
RESULT:
CODE DATE COUNT
"3443" "2009-04" 3
"3441" "2009-04" 13
"3442" "2009-04" 11
"3445" "2009-04" 72
I did use a query i.e.
SELECT CODE,date_part('month',DATE),count(CODE)
FROM employee
where
group by CODE,DATE
The above query runs fine but the months listed in the records are in form of numbers and its hard to find that a month belongs to which year. In short I want to get the result just like mention above in the RESULT section. Thanks
Try this:
SELECT CODE, to_char(DATE, 'YYYY-MM'), count(CODE)
FROM employee
where
group by CODE, to_char(DATE, 'YYYY-MM')
Depending on whether you want the result as text or a date, you can also write it like this:
SELECT CODE, date_trunc('month', DATE), COUNT(*)
FROM employee
GROUP BY CODE, date_trunc('month', DATE);
Which in your example would return this, with DATE still a timestamp, which can be useful if you are going to do further calculations on it since no conversions are necessary:
CODE DATE COUNT
"3443" "2009-04-01" 3
"3441" "2009-04-01" 13
"3442" "2009-04-01" 11
"3445" "2009-04-01" 72
date_trunc() also accepts other values, for instance quarter, year etc.
See the documentation for all values
Try any of
SELECT CODE,count(CODE),
DATE as date_normal,
date_part('year', DATE) as year,
date_part('month', DATE) as month,
to_timestamp(
date_part('year', DATE)::text
|| date_part('month', DATE)::text, 'YYYYMM')
as date_month
FROM employee
where
group by CODE,DATE;

SQL Server - Possible ways to find MAX and MIN in several records

I'm new to MSSQL and finding an elegant way to do with the followings.
I have a table called Order and the details are as follows.
orderID orderTime quantity total
*****************************************************************
1 4/1/2013 06:00:00 AM 3 300
2 4/1/2013 09:00:00 AM 1 100
3 4/2/2013 07:33:00 PM 2 265
4 4/3/2013 04:15:00 PM 1 65
*****************************************************************
Is it possible to give out the following output?
orderDate total
*******************
4/1/2013 400
4/3/2013 65
I tried to convert the orderTime into string and further group it but somehow I failed. I'm still working hard to find a way to achieve it.
I'm using SQL Server 2008.
Sure - you can convert the orderTime to a date datatype and group by that. Your output seems to indicate you want a SUM rather than MIn/MAX, but you can adjust w/ the appropriate aggregation:
select
convert(date, orderTime) as 'orderDate',
sum(total) as 'total',
min(total) as 'Min',
max(total) as 'Max'
from Order
group by convert(date, orderTime)
order by convert(date, orderTime)
You can convert the orderTime to the Date data type:
SELECT orderDate = CONVERT(Date, orderTime)
, total = SUM(total)
FROM dbo.Order (NOLOCK)
GROUP BY CONVERT(Date, orderTime)
ORDER BY orderDate;
This will return an output of:
orderDate total
*******************
4/1/2013 400
4/2/2013 265
4/3/2013 65
It depends on the data type of orderTime. You can convert it to a date field (with no time):
SELECT CAST(orderTime AS DATE), SUM(total)
FROM Table
GROUP by CAST(orderTime AS DATE);
--dmg

TS SQL - group by minute

I have a table with timestamps. What is the proper query to get the records counts for each minute for the last hour.
I.e. if now is 2:25, I want to know how many record were between 1:25 and 1:26, 1:26 and 1:27, and so on, so I have 60 results.
This will return a count of results for each minute (where you have records) in the last hour
SELECT DATEPART(n, time_stamp) AS minute, COUNT(*) as results
FROM table_name
WHERE time_stamp > DATEADD(hh, -1, GETDATE())
GROUP BY DATEPART(n, time_stamp)
This may return less than 60 results, depending on the data. If you have to have 60 results, the query is slightly different. This uses a Common Table Expression to generate a list of 60 numbers and a correlated sub-query to get the results for each minute:
WITH numbers ( num ) AS (
SELECT 1 UNION ALL
SELECT 1 + num FROM numbers WHERE num < 60 )
SELECT num AS minute,
(SELECT COUNT(*) AS results
FROM table_name
WHERE DATEPART(n, time_stamp) = num
AND time_stamp > DATEADD(hh, -1, GETDATE())
FROM numbers
To see the results, replace DATEADD(hh, -1, GETDATE()) with DATEADD(mi, -15, GETDATE()) and you'll get the results for the last 15 minutes and 0 for other minutes.
This is an alternative I have found useful for determining how many records are inserted or updated per minute. The nice thing about having your date format as a variable up front is that you can easily change it to analyze per hour instead. Hope this helps!
DECLARE #dateFormat as varchar(max) = 'yyyy-MM-dd HH:mm'
SELECT format(timeColumn, #dateFormat) AS minute, COUNT(*) as results
FROM yourTable
WHERE timeColumn > DATEADD(hh, -1, GETDATE())
GROUP BY format(timeColumn, #dateFormat)
ORDER BY 1
As you edited the question, I edit my answer. If I have understood you correctly, you want to look only at the past hour - that is, a timespan from one hour before the request is made to the current time. This is how I'd do it:
SELECT
COUNT(yourTimeStamp)
FROM yourTable
WHERE DATEADD('hh', -1, GetDate()) <= yourTimeStamp
AND yourTimeStamp < GetDate()
GROUP BY DATEPART('mm', yourTimeStamp)
I am not entirely sure that the syntax is exact. When coding in MSSQL, I would use the CURRENT_TIMESTAMP for the current time, MINUTE instead of DATEPART etc, but you get the idea for the solution.
DATEPART is what you're looking for:
declare #times table
(
someTime datetime
)
INSERT INTO #Times (sometime) values ('jan 12 2008 12:23')
INSERT INTO #Times (sometime) values ('jan 12 2008 12:34')
INSERT INTO #Times (sometime) values ('jan 12 2008 12:35')
INSERT INTO #Times (sometime) values ('jan 12 2008 12:25')
INSERT INTO #Times (sometime) values ('jan 12 2008 12:02')
INSERT INTO #Times (sometime) values ('jan 12 2008 12:09')
INSERT INTO #Times (sometime) values ('jan 12 2008 12:35')
select DATEPART(mi,sometime) AS Minute, count(*) AS NumOccurances
from #Times
WHERE SomeTime BETWEEN #Lower AND #Upper
GROUP BY DATEPART(mi, sometime)
order by NumOccurances DESC
Result:
Minute NumOccurances
35 2
2 1
9 1
23 1
25 1
34 1
If you want to group results by minute, then you can use a formatted string. This will group by number of minutes since 1/1/1900 not minute within day.
WITH formatted AS (
SELECT FORMAT(<your_datetime_column>, 'yyyy-MM-dd HH:mm') AS minute_text
FROM <your_table>
)
SELECT minute_text, COUNT(*) AS number_of_rows
FROM formatted
GROUP BY minute_text
ORDER BY 1 DESC
Here's my fixed up version of Robin's answer. I made it output the errors in the correct order and output the time as well instead of just the number which isn't super useful if you're charting this out.
WITH numbers ( num ) AS (
SELECT 1 UNION ALL
SELECT 1 + num FROM numbers WHERE num < 60 )
SELECT (SELECT DATEADD(n, -num, GETDATE())) AS TimeStamp,
(SELECT COUNT(*) AS results
FROM ErrorLogs
WHERE DATEPART(n, TimeStamp) = DATEPART(n, DATEADD(n, -num, GETDATE()))
AND TimeStamp > DATEADD(hh, -1, GETDATE())) as Count
FROM numbers
SELECT COUNT (TS) from TABLE where TABLE.TS BETWEEN(starttime, endtime)

Resources