Transactions per second - sql

I need to display particular column transactions per second count for each second.
The below query works for each minute.
Select DISTINCT column1 AS Event, Count( column1 ) AS count,
DateAdd(MINUTE, DateDiff(MINUTE, 0, [dateTimeColumn]), 0) as Time
From table
Group By column1 ,DateAdd(MINUTE, DateDiff(MINUTE, 0, [dateTimeColumn]), 0)
Test data as below:
Event Time
A 21:01:01
A 21:01:02
A 21:02:01
This results as
Event Count Time
A 2 21:01
A 1 21:02
The results should be at seconds level
Event Count Time
A 1 21:01:01
A 1 21:01:02
A 1 21:02:01
But I now need the transactions per second rather than minute. When I give DateDiff(Second...) it is giving error as date overflow error.
Please suggest

Try this instead:
;WITH CTE_MinTime AS (SELECT MIN(dateTimeColumn) AS min_time FROM Table)
SELECT
T.column1 AS Event,
COUNT(*) AS [count],
DATEADD(SECOND, DATEDIFF(SECOND, MT.min_time, T.dateTimeColumn), MT.min_time) AS [Time]
FROM
CTE_MinTime MT
CROSS JOIN Table T
GROUP BY
T.column1,
DATEADD(SECOND, DATEDIFF(SECOND, MT.min_time, T.dateTimeColumn), MT.min_time)
The problem is that when you do the DATEDIFF it's counting seconds from 1900-01-01, which is too big of a number for the default datatype.

Related

SQL Count of date values that dont match hour and day in select statement

I have a problem unique to a business process. My user needs to know how many dates, counted, are before a specific end time that do not match on the hour or the day.
Here is an example.
AAA, 2016-03-15 16:00:28.967, 2016-03-15 16:02:58.487, 2016-03-17 14:01:24.243
In the example above id AAA has 3 entries. I need to count only the ones that don't have a matching hour and day. So the actual count should come out to be 2.
I have to do this all in SQL and can't use a CTE. It needs to be either a sub select or some type of join.
Something like this.
SELECT id, date, (
SELECT COUNT(*)
FROM x
WHERE day!=day
AND hour!=hour AND date < z
) AS DateCount
Results would be AAA, 2
I am thinking some type of recursive comparison but I am not sure how to accomplish this without a CTE.
In SQL Server you can try something like this:
SELECT id, CONVERT(VARCHAR(13), [date], 120) AS [Date], COUNT(*) AS DateCount
FROM YourTable
WHERE [date] < #ENDDATE
GROUP BY id, CONVERT(VARCHAR(13), [date], 120)
SELECT a AS current_a, COUNT(*) AS b,day AS day, hour as hour,
(SELECT COUNT(*)
FROM t
WHERE day != day
AND hour != hour
AND date < z ) as datecount
FROM t GROUP BY a ORDER by b DESC

How to write SQL query for the following case.?

I have one Change Report Table which has two columns ChangedTime,FileName
Please consider this table has over 1000 records
Here I need to query all the changes based on following factors
i) Interval (i.e-1mins )
ii) No of files
It means when we have given Interval 1 min and No Of files 10.
If the the no of changed files more than 10 in any of the 1 minute interval, we need to get all the changed files exists in that 1 minute interval
Example:
i) Consider we have 15 changes in the interval 11:52 to 11:53
ii)And consider we have 20 changes in the interval 12:58 to 12:59
Now my expected results would be 35 records.
Thanks in advance.
You need to aggregate by the interval and then do the count. Assuming that an interval starting at time 0 is ok, the following should work:
declare #interval int = 1;
declare #limit int = 10;
select sum(cnt)
from (select count(*) as cnt
from t
group by DATEDIFF(minute, 0, ChangedTime)/#interval
) t
where cnt >= #limit;
If you have another time in mind for when intervals should start, then substitute that for 0.
EDIT:
For your particular query:
select sum(ChangedTime)
from (select count(*) as ChangedTime
from [MyDB].[dbo].[Log_Table.in_PC]
group by DATEDIFF(minute, 0, ChangedTime)/#interval
) t
where ChangedTime >= #limit;
You can't have a three part alias name on a subquery. t will do.
Something like this should work:
You count the number of records using the COUNT() function.
Then you limit the selection with the WHERE clause:
SELECT COUNT(FileName)
FROM "YourTable"
WHERE ChangedTime >= "StartInteval"
AND ChangedTime <= "EndInterval";
Another method that is useful in a where clause is BETWEEN : http://msdn.microsoft.com/en-us/library/ms187922.aspx.
You didn't state which SQL DB you are using so I assume its MSSQL.
select count(*) from (select a.FileName,
b.ChangedTime startTime,
a.ChangedTime endTime,
DATEDIFF ( minute , a.ChangedTime , b.ChangedTime ) timeInterval
from yourtable a, yourtable b
where a.FileName = b.FileName
and a.ChangedTime > b.ChangedTime
and DATEDIFF ( minute , a.ChangedTime , b.ChangedTime ) = 1) temp
group by temp.FileName

SQL Server - Select all top of the hour records

I have a large table with records created every second and want to select only those records that were created at the top of each hour for the last 2 months. So we would get 24 selected records for every day over the last 60 days
The table structure is Dateandtime, Value1, Value2, etc
Many Thanks
You could group by on the date part (cast(col1 as date)) and the hour part (datepart(hh, col1). Then pick the minimum date for each hour, and filter on that:
select *
from YourTable yt
join (
select min(dateandtime) as dt
from YourTable
where datediff(day, dateandtime, getdate()) <= 60
group by
cast(dateandtime as date)
, datepart(hh, dateandtime)
) filter
on filter.dt = yt.dateandtime
Alternatively, you can group on a date format that only includes the date and the hour. For example, convert(varchar(13), getdate(), 120) returns 2013-05-11 18.
...
group by
convert(varchar(13), getdate(), 120)
) filter
...
For clarity's sake, I would probably use a two-step, CTE-based approach (this works in SQL Server 2005 and newer - you didn't clearly specify which version of SQL Server you're using, so I'm just hoping you're not on an ancient version like 2000 anymore):
-- define a "base" CTE to get the hour component of your "DateAndTime"
-- column and make it accessible under its own name
;WITH BaseCTE AS
(
SELECT
ID, DateAndTime,
Value1, Value2,
HourPart = DATEPART(HOUR, DateAndTime)
FROM dbo.YourTable
WHERE DateAndTime >= #SomeThresholdDateHere
),
-- define a second CTE which "partitions" the data by this "HourPart",
-- and number all rows for each partition starting at 1. So each "last"
-- event for each hour is the one with the RN = 1 value
HourlyCTE AS
(
SELECT ID, DateAndTime, Value1, Value2,
RN = ROW_NUMBER() OVER(PARTITION BY HourPart ORDER BY DateAndTime DESC)
FROM BaseCTE
)
SELECT *
FROM HourlyCTE
WHERE RN=1
Also: I wasn't sure what exactly you mean by "top of the hour" - the row that's been created right at the beginning of each hour (e.g. at 04:00:00) - or rather the last row created in that hour's time span? If you mean the first one for each hour - then you'd need to change the ORDER BY DateAndTime DESC to ORDER BY DateAndTime ASC
You can use option with EXISTS operator
SELECT *
FROM dbo.tableName t
WHERE t.DateAndTime >= #YourDateCondition
AND EXISTS (
SELECT 1
FROM dbo.tableName t2
WHERE t2.Dateandtime >= DATEADD(HOUR, DATEDIFF(HOUR, 0, t.Dateandtime), 0)
AND t2.Dateandtime < DATEADD(HOUR, DATEDIFF(HOUR, 0, t.Dateandtime)+1, 0)
HAVING MAX(t2.Dateandtime) = t.Dateandtime
)
OR option with CROSS APPLY operator
SELECT *
FROM dbo.test83 t CROSS APPLY (
SELECT 1
FROM dbo.test83 t2
WHERE t2.Dateandtime >= DATEADD(HOUR, DATEDIFF(HOUR, 0, t.Dateandtime), 0)
AND t2.Dateandtime < DATEADD(HOUR, DATEDIFF(HOUR, 0, t.Dateandtime)+1, 0)
HAVING MAX(t2.Dateandtime) = t.Dateandtime
) o(IsMatch)
WHERE t.DateAndTime >= #YourDateCondition
For improving performance use this index:
CREATE INDEX x ON dbo.test83(DateAndTime) INCLUDE(Value1, Value2)
Try:
select * from mytable
where datepart(mi, dateandtime)=0 and
datepart(ss, dateandtime)=0 and
datediff(d, dateandtime, getdate()) <=60
You can use window functions for this:
select dateandtime, val1, val2, . . .
from (select t.*,
row_number() over (partition by cast(dateandtime as date), hour(dateandtime)
order by dateandtime
) as seqnum
from t
) t
where seqnum = 1
The function row_number() assigns a sequential number to each group defined by the partition clause -- in this case each hour of each day. Within this group, it orders by the dateandtime value, so the one closest to the top of the hour gets a value of 1. The outer query just selects this one record for each group.
You may need an additional filter clause to get records in the last 60 days. Use this in the subquery:
where dateandtime >= getdate() - 60
This helped me get the top of the hour. Anything that ends in ":00:00".
WHERE (CAST(DATETIME as VARCHAR(19))) LIKE '%:00:00'

SQL SELECT Only Closest To 15-Minute Timestamp

I would like to do a SQL SELECT for the closest value to each 15-minute time value. For example:
00:15,
00:30,
00:45,
01:00,
01:15 etc...
based on timestamps(time) that are not quite on the 00 second stamped using the following if have managed to round every value down to the closest 15 minutes but I only want the closest one e.g.
SELECT dateadd(minute, -1 * datediff(minute, 0,
cast(convert(varchar(20),[time],100) as smalldatetime)) % 15,
dateadd(minute, datediff(minute, 0, [time]), 0)) as [TIMESTAMP],
cast(convert(varchar(20),[time],100) as smalldatetime), [time],
tagname , value
FROM hdata
INNER JOIN rtdata
ON hdata.tag_id = rtdata.id
WHERE tagname = 'M1_WH_004'
order by [TIMESTAMP] desc
(note: i need the inner join to pull the tagname as they are not in the hdata table)
produces:
Therefore, for each 15 minutes, I only want the value closest to the 15-min boundary. For the data above, it would be the 09:45:15.383 and 09:30:17.463 for the data for 09:45 and 09:30 respectively.
Do I need a subquery or case statement?
Any help would be greatly appreciated!
Further to this, a had a table that looked like the data in the solution (data for every 15 minutes) already and the subquery performed a calculation based on the last two values like so:
SELECT DD1.[TIME_STAMP] AS [TIME_STAMP], DD1.[kWh1] AS [kWh1], DD1.[kWh2] AS [kWh2], (DD1.[kWh1] + DD1.[kWh2]) AS [Total] FROM (SELECT a.ID
,a.TIME_STAMP
,(a.[1_M1_Wh] - (SELECT TOP 1 b.[1_M1_Wh] FROM TagCapture b WHERE b.TIME_STAMP = DATEADD(MINUTE, -15, a.TIME_STAMP))) * 0.04 AS kWh1
,(a.[1_M2_Wh] - (SELECT TOP 1 b.[1_M2_Wh] FROM TagCapture b WHERE b.TIME_STAMP = DATEADD(MINUTE, -15, a.TIME_STAMP))) * 0.04 AS kWh2
FROM [TagCapture] a) DD1
How can I use the solution provided in this query? I'm a little confused with all the subqueries.
i.e. so based on the data defined by the t subquery take the count value for one 15 minute subtract from previous and multiply to get required value where would I insert the t subquery in each FROM clause? I can't seem to get it to work. The above is just where the t query would define the two different tagnames for 'M1' and 'M2'.
Thanks again in advance!!
It looks like you are using SQL Server. If so, then you can use row_number() to solve this.
select t.*
from (select t.*, row_number() over (partition by tagname, time15 order by time) as seqnum
from (SELECT dateadd(minute, -1 * datediff(minute, 0, cast(convert(varchar(20),[time],100) as smalldatetime)) % 15, dateadd(minute, datediff(minute, 0, [time]), 0)) as [TIMESTAMP], cast(convert(varchar(20),[time],100) as smalldatetime) as time15,
[time], tagname , value
FROM hdata INNER JOIN rtdata
ON hdata.tag_id = rtdata.id
WHERE tagname = 'M1_WH_004'
) t
) t
where seqnum = 1

sum of time datatype in sql

i have a table named tblAttendanceDailySummary and there is a field is in time datatype named timeAttendanceHour(like 09:44:25). I want to sum of this field due to end of the month.I mean one employee's one month working time need to calculate.How can i sum time datatype.
The time data type has a range of 00:00:00.0000000 through 23:59:59.9999999 so you can't cast to time. You have to calculate the hour, minute and second instead.
Something like this could work for you
select H.Val, M.Val, S.Val
from (
--Your query goes here
select dateadd(second, sum(datediff(second, 0, timeAttendanceHour)), 0) as sumtime
from YourTable
) as T
cross apply (select datedifF(hour, 0, T.sumTime)) as H(Val)
cross apply (select datediff(minute, 0, dateadd(hour, -H.Val, T.sumTime))) as M(Val)
cross apply (select datediff(second, 0, dateadd(hour, -H.Val, dateadd(minute, -M.Val, T.sumTime)))) as S(Val)
If you want the result as HH:MM:SS you can use this:
select cast(H.Val as varchar(10))+':'+right(M.Val+100, 2)+':'+right(S.Val+100, 2)
How about converting the components to a standard integer and summing them:
select sum(second(timeAttendanceHour))/60 +
sum(minute(timeAttendanceHour)) +
sum(hour(timeAttendance))*60 as MonthlyMinutes, intMonthID
from tblAttendanceDailySummary
where intYear = 2012
group by intEmployeeID, intMonthID