Here I need to compare date using SQL Server 2008. I want show details of the table if the specific date appears more than one time.
Example:
create table datetest
(
columnx nvarchar(10),
columny nvarchar(10),
coldate date,
coltime datetime
)
insert into datetest values('a123','b123','2014-01-01','01:05:00.000');
insert into datetest values('a123','b456','2014-01-01','02:15:00.000');
insert into datetest values('a123','b789','2014-01-01','03:25:00.000');
insert into datetest values('a321','b321','2014-02-03','10:05:00.000');
insert into datetest values('a243','b243','2014-03-04','11:05:00.000');
insert into datetest values('a243','b243','2014-03-04','12:05:00.000');
insert into datetest values('a243','b243','2014-03-04','12:05:00.000');
Now I need to show only that records whose dates are greater than one appear in the table.
Expected result:
columnx columny coldate coltime
-------------------------------------------------------
a123 b123 2014-01-01 1900-01-01 01:05:00.000
a123 b456 2014-01-01 1900-01-01 02:15:00.000
a123 b789 2014-01-01 1900-01-01 03:25:00.000
a243 b243 2014-03-04 1900-01-01 11:05:00.000
a243 b243 2014-03-04 1900-01-01 12:05:00.000
a243 b243 2014-03-04 1900-01-01 12:05:00.000
My attempt:
select *
from datetest
where coldate = '2014-01-01' or coldate = '2014-03-04';
Note: But this is not the right way for the large records to check.
try like this
select * from datetest
where coldate in (select coldate from
datetest group by coldate having count(*) > 1)
DEMO
Related
I have a table which stores records for Daylight saving and non-Daylight savings
CREATE TABLE #tmp
(
ID int,
IntervalName nvarchar(100),
StartDate datetime,
EndDate Datetime,
offset numeric(5, 2)
)
INSERT INTO #tmp
VALUES (1, 'EDT', '2022-03-13 07:00:00.000', '2022-11-06 06:00:00.000',-4.00)
INSERT INTO #tmp
VALUES (2, 'EST', '2022-11-06 06:00:00.000', '2023-03-12 07:00:00.000', -5.00)
I have my transactional tables which have Date column in the GMT timezone.
ID DatetimeGMT DatetimeLocal
---------------------------------------------------------
1 2022-11-05 07:00:00.000 2022-11-05 03:00:00.000
2 2022-11-10 06:00:00.000 2023-11-10 01:00:00.000
Now my DatetimeLocal column is calculating the offset hours based on the DatetimeGMT column.
The row with ID = 1 falls under offset -4 and the row with ID = 2 falls under offset -5.
Is there any suggestion how we can achieve this?
If you have the offsets all stored in a table like that, then you just need to JOIN to find the correct one.
eg
drop table if exists #tmp
drop table if exists #tran
go
CREATE TABLE #tmp
(
ID int,
IntervalName nvarchar(100),
StartDate datetime,
EndDate Datetime,
offset numeric(5, 2)
)
INSERT INTO #tmp
VALUES (1, 'EDT', '2022-03-13 07:00:00.000', '2022-11-06 06:00:00.000',-4.00)
INSERT INTO #tmp
VALUES (2, 'EST', '2022-11-06 06:00:00.000', '2023-03-12 07:00:00.000', -5.00)
create table #tran(id int primary key, DateTimeUTC datetime)
insert into #tran(id,DateTimeUTC) values (1,'2022-11-05 07:00:00.000'),(2,'2022-11-10 06:00:00.000')
select t.id, t.DateTimeUTC, dateadd(hour,offset,t.DateTimeUTC) DateTimeLocal, tz.offset
from #tran t
join #tmp tz
on t.DateTimeUTC >= tz.StartDate
and t.DateTimeUTC < tz.EndDate
outputs
id DateTimeUTC DateTimeLocal offset
----------- ----------------------- ----------------------- ---------------------------------------
1 2022-11-05 07:00:00.000 2022-11-05 03:00:00.000 -4.00
2 2022-11-10 06:00:00.000 2022-11-10 01:00:00.000 -5.00
SQL Server 2016 and later have the offsets built-in, so you can write queries like
select t.id,
t.DateTimeUTC,
cast(t.DateTimeUTC at time zone 'UTC' at time zone 'EASTERN STANDARD TIME' as datetime) DateTimeLocal
from #tran t
We have data in a Visit_Time column stored in 24Hrs date format as well as 12Hrs.
The data is inserted into a table from a different type of source like MobileApp and Web source etc.
Example:
Create table VisitorDetails
(
Visit_Date Date,
Visit_Time varchar(12)
)
VisitorDetails
----------------------------
Visit_Date Visit_Time
----------------------------
2020-01-01 01:00PM
2020-01-02 17:00
2020-01-03 04:00PM
2020-01-04 20:00
-----------------------------
How to convert Visit_Time Column either in 12 Hrs format or 24 Hrs formate?
Need Result like below
VisitorDetails 12Hrs 24Hrs
---------------------------- --------------
Visit_Date Visit_Time (OR) Visit_Time
---------------------------- --------------
2020-01-01 01:00PM 13:00
2020-01-02 05:00PM 17:00
2020-01-03 04:00PM 16:00
2020-01-04 08:00PM 20:00
----------------------------- --------------
12 hour format
declare #t1 time
declare #t2 time
declare #t3 time
set #t1 = '14:40'
set #t2 = '17:00'
set #t3 = '01:00PM'
select CONVERT(varchar(15),#t1,100)
select CONVERT(varchar(15),#t2,100)
select CONVERT(varchar(15),#t3,100)
When fetching your rows you could do:
SELECT [Visit_Date], LEFT(PARSE([Visit_Time] AS time), 5)
FROM [VisitorDetails]
for a consistent time format.
However, I would strongly recommend returning time values from the db and do the display modification in your app.
Please try below solution:
--24 Hour Format
SELECT CONVERT(VARCHAR(5),CONVERT(DATETIME, '01:00PM', 0), 108)
SELECT CONVERT(VARCHAR(5),CONVERT(DATETIME, '17:00', 0), 108)
--12 Hour Format
SELECT LTRIM(RIGHT(CONVERT(VARCHAR(20), CONVERT(DATETIME, '01:00PM', 0), 100), 7))
SELECT LTRIM(RIGHT(CONVERT(VARCHAR(20), CONVERT(DATETIME, '17:00', 0), 100), 7))
To Store 24 hrs format declare the Column data type as DATETIME Instead of Varchar(12)
DECLARE #T TABLE(
ID INT IDENTITY(1,1),
Visit_DATE_TIME varchar(20))
12 hrs Data insertion:
INSERT INTO #T VALUES('24-MAY-2020 10:30PM')
INSERT INTO #T VALUES('25-MAY-2020 11:30AM')
24 hrs Data insertion:
INSERT INTO #T VALUES('26-MAY-2020 16:30')
INSERT INTO #T VALUES('28-MAY-2020 22:30')
Query
SELECT *, CAST(VISIT_DATE_TIME as DATE) as Visit_Date ,
CAST(VISIT_DATE_TIME as TIME) as Visit_Time_24,
RIGHT(CONVERT(DATETIME,RTRIM(VISIT_DATE_TIME), 109),7) as Visit_Time_12
FROM #T
I have a table in sql server 2012,with column named Duration as Time datatype.i want to update this column base on difference of dates, by adding the difference to this duration column.how can I do this in SP.
ID StartDate EndDate Duration
1 2017-02-27 09:10:35 2017-02-27 09:25:35 00:15
2 2017-02-27 09:26:35 2017-02-27 09:36:35 00:25
Durtion always less than 24 hours.
One method is:
update t
set duration = cast(dateadd(ms, datediff(ms, startdate, enddate), 0) as time);
This is an easy one. Just use a simple arithmetic operation:
DECLARE #TABLE TABLE (Start DATETIME, Finish DATETIME, Duration TIME);
INSERT INTO #TABLE VALUES ('02/28/2017 08:00','02/28/2017 08:30','');
INSERT INTO #TABLE VALUES ('02/28/2017 09:00','02/28/2017 09:40','');
INSERT INTO #TABLE VALUES ('02/28/2017 10:02','02/28/2017 11:53','');
INSERT INTO #TABLE VALUES ('02/28/2017 11:56','02/28/2017 12:45','');
INSERT INTO #TABLE VALUES ('02/28/2017 13:45','02/28/2017 23:59','');
UPDATE #TABLE
SET Duration = Finish - Start;
SELECT * FROM #TABLE;
Returns:
Start Finish Duration
---------------------------------------------------------
28/02/2017 08:00:00 28/02/2017 08:30:00 00:30:00
28/02/2017 09:00:00 28/02/2017 09:40:00 00:40:00
28/02/2017 10:02:00 28/02/2017 11:53:00 01:51:00
28/02/2017 11:56:00 28/02/2017 12:45:00 00:49:00
28/02/2017 13:45:00 28/02/2017 23:59:00 10:14:00
The only caveat here being that they need to be on the same day. You explicitly stated that the duration is never more than one day, so that should be fine.
If you want to add the result to the original value of Duration, then you would just add it on...
INSERT INTO #TABLE VALUES ('02/27/2017 08:00','02/28/2017 08:30','00:15');
INSERT INTO #TABLE VALUES ('02/28/2017 09:00','02/28/2017 09:40','00:14');
INSERT INTO #TABLE VALUES ('02/28/2017 10:02','02/28/2017 11:53','00:13');
INSERT INTO #TABLE VALUES ('02/28/2017 11:56','02/28/2017 12:45','02:16');
INSERT INTO #TABLE VALUES ('02/28/2017 13:45','02/28/2017 23:59','00:17');
UPDATE #TABLE
SET Duration = Duration + (Finish - Start);
Returns:
Start Finish Duration
---------------------------------------------------------
27/02/2017 08:00:00 28/02/2017 08:30:00 00:45:00
28/02/2017 09:00:00 28/02/2017 09:40:00 00:54:00
28/02/2017 10:02:00 28/02/2017 11:53:00 02:04:00
28/02/2017 11:56:00 28/02/2017 12:45:00 03:05:00
28/02/2017 13:45:00 28/02/2017 23:59:00 10:31:00
UPDATE [TABLE] SET [DURATION] = CONVERT(varchar(5),DATEADD(minute, DATEDIFF(MINUTE, StartDate, EndDate), 0), 114);
None of the other answers attempt to SUM the duration which is what you expect.
DECLARE #TABLE TABLE (ID INT, StartTime DATETIME, EndTime DATETIME, Duration TIME);
INSERT INTO #TABLE VALUES (1, '02/28/2017 01:00','02/28/2017 06:30','');
INSERT INTO #TABLE VALUES (2, '02/28/2017 09:00','02/28/2017 23:40','');
INSERT INTO #TABLE VALUES (3, '03/01/2017 10:02','03/01/2017 21:53','');
UPDATE t
SET Duration=
CONVERT(TIME,
(
SELECT DATEADD(ms, SUM(DATEDIFF(ms, '00:00:00.000', EndTime - StartTime)), '00:00:00.000')
FROM #TABLE it
WHERE it.EndTime<= t.EndTime
)
)
FROM #TABLE t;
SELECT * FROM #TABLE;
I'm using SQL Server 2008 and looking how to create such a query:
I have a table:
Username nvarchar(50), LogDate datetime
Test1, 2012.01.01 00:00:00
Test2, 2012.01.01 00:00:02
Test1, 2012.01.01 00:00:05
Test3, 2012.01.01 00:00:06
Test1, 2012.01.02 00:01:01
Test2, 2012.01.02 00:02:50
Test1, 2012.01.02 00:01:01
Every few seconds users send updates to insert current datetime with his username in to the log table. I need to calculate how much hours users were "online" every day.
I assume query should sum DateDiff between two rows with the same username grouped by day.
I tried using rank, but haven't got what I want.
Thank you for your help in advance.
You can extract the date part of the DateTime and group by the UserName to use DateDiff on the MIN / MAX Values:
Table and Data Setup:
create table UserLog (Username nvarchar(50), LogDate DateTime);
insert into UserLog Values('Test1', '2012-01-01 00:00:00');
insert into UserLog Values('Test2', '2012-01-01 00:00:02');
insert into UserLog Values('Test1', '2012-01-01 00:00:05');
insert into UserLog Values('Test3', '2012-01-01 00:00:06');
insert into UserLog Values('Test3', '2012-01-01 00:01:26');
insert into UserLog Values('Test3', '2012-01-01 00:03:22');
insert into UserLog Values('Test3', '2012-01-01 00:05:42');
insert into UserLog Values('Test3', '2012-01-01 00:00:06');
insert into UserLog Values('Test1', '2012-01-02 00:01:01');
insert into UserLog Values('Test2', '2012-01-02 00:02:50');
insert into UserLog Values('Test1', '2012-01-02 00:01:01');
Then you can SELECT as follows:
select UserName, CAST(LogDate AS DATE) as BusinessDay,
MIN(LogDate) as FirstLogEntry, MAX(LogDate) as LastLogEntry,
DATEDIFF(second,MIN(LogDate), MAX(LogDate)) as ElapsedSeconds
FROM UserLog
GROUP BY Username, CAST(LogDate AS DATE)
This will yield the following results and you can calculate hours from the seconds. I showed seconds based on your sample data with test3 user expanded:
UserName BusinessDay FirstLogEntry LastLogEntry ElapsedSeconds
-------- ----------- ----------------------- ----------------------- --------------
Test1 2012-01-01 2012-01-01 00:00:00.000 2012-01-01 00:00:05.000 5
Test2 2012-01-01 2012-01-01 00:00:02.000 2012-01-01 00:00:02.000 0
Test3 2012-01-01 2012-01-01 00:00:06.000 2012-01-01 00:05:42.000 336
Test1 2012-01-02 2012-01-02 00:01:01.000 2012-01-02 00:01:01.000 0
Test2 2012-01-02 2012-01-02 00:02:50.000 2012-01-02 00:02:50.000 0
the data is in 15 minute interval:
Time Value
2010-01-01 00:15 3
2010-01-01 00:30 2
2010-01-01 00:45 4
2010-01-01 01:00 5
2010-01-01 01:15 1
2010-01-01 01:30 3
2010-01-01 01:45 4
2010-01-01 02:00 12
2010-01-01 02:15 13
2010-01-01 02:30 12
2010-01-01 02:45 14
2010-01-01 03:00 15
2010-01-01 03:15 3
2010-01-01 03:30 2
2010-01-01 03:45 3
2010-01-01 04:00 5
..........
..........
..........
2010-01-02 00:00
Typically there will be 96 points.
According to the values, we may notice that the values from 00:15 to 01:45 are close to each other, and from 02:00 to 03:00 they are close to each other, and from 03:15 to 04:00 they are close to each other.
Based on the "close to each other" rule, I want the data to be "grouped" into 3 parts:
00:15 to 01:45
02:00 to 03:00
03:15 to 04:00
Please consider that the data could be random, and could be grouped into more than 3 parts according to the rule defined above, but maximum should not be more than 10 parts. And the grouping must honor the time sequence, for example, you cannot just put 00:15/02:30/04:45 into 1 group because these 3 points are NOT consecutive.
Please give some thoughts how to implement it in t-sql.
updated:
The value could be:
Time Value
2010-01-01 00:15 3
2010-01-01 00:30 2
2010-01-01 00:45 4
2010-01-01 01:00 5
2010-01-01 01:15 1
2010-01-01 01:30 3
2010-01-01 01:45 4
2010-01-01 02:00 12
2010-01-01 02:15 13
2010-01-01 02:30 4 --suddenly decreased
2010-01-01 02:45 14
2010-01-01 03:00 15
2010-01-01 03:15 3
2010-01-01 03:30 2
2010-01-01 03:45 3
2010-01-01 04:00 5
..........
..........
..........
2010-01-02 00:00
for these kinds of situation, we should not group 02:30 separately, because we want the group size has to be at least 3 points, and we will put that point (02:30) to the previous group (from 02:00 to 03:00).
Declare and populate testdata:
set nocount on
declare #result table(mintime datetime, maxtime datetime)
declare #t table(time datetime, value int)
-- variation is how much difference will be allowed from one row to the next
declare #variation int
set #variation = 5
insert #t values('2010-01-01 00:15',3)
insert #t values('2010-01-01 00:30',2)
insert #t values('2010-01-01 00:45',4)
insert #t values('2010-01-01 01:00',5)
insert #t values('2010-01-01 01:15',1)
insert #t values('2010-01-01 01:30',3)
insert #t values('2010-01-01 01:45',4)
insert #t values('2010-01-01 02:00',12)
insert #t values('2010-01-01 02:15',13)
insert #t values('2010-01-01 02:30',12)
insert #t values('2010-01-01 02:45',14)
insert #t values('2010-01-01 03:00',15)
insert #t values('2010-01-01 03:15',3)
insert #t values('2010-01-01 03:30',2)
insert #t values('2010-01-01 03:45',3)
insert #t values('2010-01-01 04:00',5)
Code:
a:
;with t as
( -- add a rownumber
select *, rn = row_number() over(order by time) from #t
), a as
(-- increase group if current row's value varies more than #variation from last row's value
select time, value, rn, 0 grp from t where rn = 1
union all
select t.time, t.value, t.rn, case when t.value between
a.value - #variation and a.value +#variation
then grp else grp+1 end
from t join a on
t.rn = a.rn +1
)
insert #result
select min(time), max(time) from a group by grp
if ##rowcount > 10
begin
-- this will activate if more than 10 groups of numbers are found
-- start over with higher tolerance for variation
set #variation=#variation + 1
delete #result
goto a
end
select convert(char(5), mintime,114) + ' to ' + convert(char(5), maxtime,114)
from #result
Result here:
https://data.stackexchange.com/stackoverflow/q/110891/declare-and-populate-testdata
Since your question changed so much, here is a new answer to the new question, I only included the code part.
declare #t table(time datetime, value int)
declare #variation float
set #variation = 2
set nocount on
insert #t values('2010-01-01 00:15',3)
insert #t values('2010-01-01 00:30',2)
insert #t values('2010-01-01 00:45',4)
insert #t values('2010-01-01 01:00',5)
insert #t values('2010-01-01 01:15',1)
insert #t values('2010-01-01 01:30',3)
insert #t values('2010-01-01 01:45',4)
insert #t values('2010-01-01 02:00',52)
insert #t values('2010-01-01 02:15',5)
insert #t values('2010-01-01 02:30',52)
insert #t values('2010-01-01 02:45',54)
insert #t values('2010-01-01 03:00',55)
insert #t values('2010-01-01 03:15',3)
insert #t values('2010-01-01 03:30',2)
insert #t values('2010-01-01 03:45',3)
insert #t values('2010-01-01 04:00',5)
declare #result table(mintime datetime, maxtime datetime)
a:
delete #result
;with t as
(
select *, rn = row_number() over(order by time), log(value) lv from #t where datediff(day, time, '2010-01-01') = 0
), a as
(
select time, lv, rn, 0 grp from t where rn = 1
union all
select t1.time, a.lv, t1.rn,
case when exists (select 1 from t t2 where t1.rn between rn + 1 and rn + 3 and
lv between t1.lv - #variation and t1.lv +#variation) then grp else grp + 1 end
from t t1 join a on
t1.rn = a.rn +1
)
insert #result
select min(time), max(time) from a group by grp
if ##rowcount > 10
begin
set #variation=#variation + .5
goto a
end
select * from #result
Result:
mintime maxtime
2010-01-01 00:15:00.000 2010-01-01 01:45:00.000
2010-01-01 02:00:00.000 2010-01-01 03:00:00.000
2010-01-01 03:15:00.000 2010-01-01 04:00:00.000