I have two fields in sql date1 varchar(4) and date2 varchar(4). The date format is just HHmm where HH is the hours and mm is the minutes.
Is there anyway in SQL which we can add the two timestamps together and work out how many hours and minutes?
e.g.
date1 = 0230 date2 = 0145 will total 0415
date1 = 0030 date2 = 0035 will total 0105
declare #d1 varchar(4), #d2 varchar(4), #dif int
set #d1 = '0230'
set #d2 = '0145'
set #dif = (CAST(left(#d1, 2) as int) * 60) + (CAST(left(#d2, 2) as int) * 60) + CAST(right(#d1, 2) as int) + CAST(right(#d2, 2) as int)
select RIGHT('00' + cast(floor(#dif / 60) as varchar), 2) + RIGHT('00' + CAST(#dif % 60 as varchar),2)
Not sure these are really timestamps, what not store them as integers?
Anyhow.. not sure there is a mysql function for this.
You can browse: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html
Not sure it will offer much help.
If you store them as seconds, then you can simply have mysql add them, otherwise pull them into a script, convert them to seconds, add them together and then convert to a more readable format if desired.
Try this (use time or date time):
select ADDTIME(time1,time2);
In mysql time is of the form
'01:02:03'
and date time is
'2003-12-31 01:02:03'
IF you happen to be using SQL Server you may also be able to use the DATEDIFF function described here: http://msdn.microsoft.com/en-us/library/ms189794.aspx
This will let you get the difference between any part of a datetime value. DATEADD may be of use for this as well depending on how you want to handle it.
Related
It must be very simple, but I don't know SQL language very well.
I need to filter data by date which is in this format:
How to do it right to filter data this way?
FROM [TableName] where
FileDate>=20220505
I've already tried the command LEFT and CAST but with no success
Something like this may work:
declare #now Datetime = getdate();
declare #intNow int = cast(cast(datepart(year, #now) as varchar(4)) + RIGHT('00'+CAST(datepart(month, #now) AS VARCHAR(2)),2) + RIGHT('00'+CAST(datepart(day, #now) AS VARCHAR(2)),2) as int)
Although if you have your date to check against in the right format e.g. using:
declare #dateToCheck Datetime = cast(cast(20220505 as varchar) as datetime)
And then
FileDate>= #dateToCheck
it should work
You can create an integer representation of your datetime by multiplying and adding the date parts:
year * 10000 20220000
month * 100 500
day 5
-------------------------
20220505
...
FROM [TableName]
WHERE (DATEPART(year, [FileDate]) * 10000) + (DATEPART(month, [FileDate]) * 100) + (DATEPART(day, [FileDate])) >= 20220505
However I'd still look into fixing the condition input format instead.
Credit to #Rangani in Yesterday's date in SSIS package setting in variable through expression for "multiply and add instead of string concat" trick
I am trying to create a table in SQL which is about Music, it should contain songDuration. Which means I gotta hold minutes:seconds information in the table. But i have no idea what to use for the type. I am using SQL server.
Edit: I want to use the database for an ASP.NET Core web application. I was using a ready-to-use SQL database like northwnd. Now, I am trying to create one. So, I will not see the timing with SELECT function in SQL query. So, I need to use something that makes it mm:ss otomaticly. Is there is a type that I can decleare like that?
create table musics(
songDuration type,
...)
Why just don't you use int?
So you could calculate duration in the way you like.
E.g. minutes,hours, etc.
There's a datatype time which would be the logical choice, that stores it in format HH:mm:ss with an optional amount of fractional seconds determined by the size you declare the field (e.g. time(3) holds it to three decimal places)
If your source data is already in this notation it makes it getting it in the table easy and simple sorting/filtering operates as you expect. The downside to doing this is if you want to do certain operations such as SUM or AVG (because as a_horse_with_no_name pointed out in their comment) time technically represents a point in time not a duration and you'd have to do some workaround like so:
SELECT totalduration = SUM(DATEDIFF(SECOND, '0:00:00', duration))
FROM dbo.table
Alternatively you could store the number of (say) seconds in the duration using an int, but if you don't already have the information in that format you'd have to do some (light) conversion when inserting the data, and then back if you want to display in mm:ss
e.g:
SELECT CONVERT(varchar, DATEADD(SECOND, durationinseconds, 0), 8) FROM dbo.table
which would convert it back to hh:mm:ss format.
I do this by using an int column, and store the seconds there.
In your client you can calculate from the seconds howmany days, hours, minutes and seconds it is and display it like you want.
To display it in sql you can use this for example
declare #seconds int = 350
select right('00' + convert(varchar, datepart(hour, dateadd(s, #seconds, 0)) + ((#seconds / 86400) * 24)), 2)
+ ':' + right('00' + convert(varchar, datepart(minute, dateadd(s, #seconds, 0))), 2)
+ ':' + right('00' + convert(varchar, datepart(second, dateadd(s, #seconds, 0))), 2)
this will display
00:05:50
which is 0 hours, 5 minutes and 50 seconds
IF the value of seconds is larger than a day, this will be no problem. The number of hours will simply be greater
a value of 350000 will display 97:13:20
I am working on a query, where I have to fill a table's column ([Result_DateTime]) with datetime values.
The datetime based on two columns, both integer. One contains the date and the other is the time, as it is.
As you can see from the picture, it is a bit difficult to merge and convert these values to an actual datetime, because of the way they are stored. Mainly the time value causing problems.
I concluded how to convert the date column:
CONVERT(DATETIME, LEFT(20200131, 8))
but then I got stuck - what to do with the time and how to merge the two into one datetime effectively?
Using function STUFF looks nasty...
Could you help me out please? I am using SQL Server 2014
Below is one method to do it:
SELECT CAST(Convert(DATE, LEFT(DATEUPDT, 8)) AS VARCHAR(10)) +' '+CAST (TIMEUPDT/100 AS VARCHAR(4)) + ':' + CAST(TIMEUPDT%(100 * (TIMEUPDT/100)) AS VARCHAR(10))+':00'
FROM TEST_TABLE_TIME;
I think I found one solution. What I tried is to avoid using varchar conversions because of how the time column's zeros are cut off. However, I am not convinced that this is the most effective way to do so:
DECLARE #DateInt int = 20200131
DECLARE #TimeInt int = 345 -- 03:45:00
SELECT CONVERT(DATETIME, LEFT(#DateInt, 8)) +
CAST(DATEADD(second, FLOOR(#TimeInt / 100) * 3600 + FLOOR(#TimeInt / 1) % 100 * 60, 0) as datetime)
I was testing it with various time values, it is working.
I am trying to take a date which is in a varchar column in a table, add 1 day to it, and set it as the value of a datetime variable. This is part of a process that runs daily and I need to make sure the day resets to one at the end of the month. Or at the end of the year it doesn't increase from 151231 to 151232. The problem I am having is converting #Date back to numeric in the form YYMMDD. For example VIRN_CHK = '151231', #Date as written below is 'Jan 1 2016 12:00AM'. I need to convert it to 160101 so I can save it in a column in another table of type numeric(6,0).
DECLARE #Date as datetime
set #Date = convert(varchar,dateadd(d, 1,(select top(1) VIRN_CHK from STAGE_INST)))
update cdcdatei
set OT_DATE = #Date
This will work by rebuilding the string format
SELECT RIGHT(YEAR('2015-11-01'),2)
+ RIGHT('00' + CAST(MONTH('2015-11-01') AS VARCHAR(2)),2)
+ RIGHT('00' + CAST(DAY('2015-11-01') AS VARCHAR(2)),2)
So you need to extract the year, month and day numbers from the date? You can to that using DATEPART
DATEPART(yy,dateadd) AS DateYear,
DATEPART(mm,dateadd) AS DateMonth,
DATEPART(dd,dateadd) AS DateDay
then you can multiply and sum them to obtain what you need
VIRN_CHK = DateDay + DateMont * 100 + DateYear * 10000
Here is the issue I am having: I have a large query that needs to compare datetimes in the where clause to see if two dates are on the same day. My current solution, which sucks, is to send the datetimes into a UDF to convert them to midnight of the same day, and then check those dates for equality. When it comes to the query plan, this is a disaster, as are almost all UDFs in joins or where clauses. This is one of the only places in my application that I haven't been able to root out the functions and give the query optimizer something it can actually use to locate the best index.
In this case, merging the function code back into the query seems impractical.
I think I am missing something simple here.
Here's the function for reference.
if not exists (select * from dbo.sysobjects
where id = object_id(N'dbo.f_MakeDate') and
type in (N'FN', N'IF', N'TF', N'FS', N'FT'))
exec('create function dbo.f_MakeDate() returns int as
begin declare #retval int return #retval end')
go
alter function dbo.f_MakeDate
(
#Day datetime,
#Hour int,
#Minute int
)
returns datetime
as
/*
Creates a datetime using the year-month-day portion of #Day, and the
#Hour and #Minute provided
*/
begin
declare #retval datetime
set #retval = cast(
cast(datepart(m, #Day) as varchar(2)) +
'/' +
cast(datepart(d, #Day) as varchar(2)) +
'/' +
cast(datepart(yyyy, #Day) as varchar(4)) +
' ' +
cast(#Hour as varchar(2)) +
':' +
cast(#Minute as varchar(2)) as datetime)
return #retval
end
go
To complicate matters, I am joining on time zone tables to check the date against the local time, which could be different for every row:
where
dbo.f_MakeDate(dateadd(hh, tz.Offset +
case when ds.LocalTimeZone is not null
then 1 else 0 end, t.TheDateINeedToCheck), 0, 0) = #activityDateMidnight
[Edit]
I'm incorporating #Todd's suggestion:
where datediff(day, dateadd(hh, tz.Offset +
case when ds.LocalTimeZone is not null
then 1 else 0 end, t.TheDateINeedToCheck), #ActivityDate) = 0
My misconception about how datediff works (the same day of year in consecutive years yields 366, not 0 as I expected) caused me to waste a lot of effort.
But the query plan didn't change. I think I need to go back to the drawing board with the whole thing.
This is much more concise:
where
datediff(day, date1, date2) = 0
You pretty much have to keep the left side of your where clause clean. So, normally, you'd do something like:
WHERE MyDateTime >= #activityDateMidnight
AND MyDateTime < (#activityDateMidnight + 1)
(Some folks prefer DATEADD(d, 1, #activityDateMidnight) instead - but it's the same thing).
The TimeZone table complicates matter a bit though. It's a little unclear from your snippet, but it looks like t.TheDateInTable is in GMT with a Time Zone identifier, and that you're then adding the offset to compare against #activityDateMidnight - which is in local time. I'm not sure what ds.LocalTimeZone is, though.
If that's the case, then you need to get #activityDateMidnight into GMT instead.
where
year(date1) = year(date2)
and month(date1) = month(date2)
and day(date1) = day(date2)
Make sure to read Only In A Database Can You Get 1000% + Improvement By Changing A Few Lines Of Code so that you are sure that the optimizer can utilize the index effectively when messing with dates
this will remove time component from a date for you:
select dateadd(d, datediff(d, 0, current_timestamp), 0)
Eric Z Beard:
I do store all dates in GMT. Here's the use case: something happened at 11:00 PM EST on the 1st, which is the 2nd GMT. I want to see activity for the 1st, and I am in EST so I will want to see the 11PM activity. If I just compared raw GMT datetimes, I would miss things. Each row in the report can represent an activity from a different time zone.
Right, but when you say you're interested in activity for Jan 1st 2008 EST:
SELECT #activityDateMidnight = '1/1/2008', #activityDateTZ = 'EST'
you just need to convert that to GMT (I'm ignoring the complication of querying for the day before EST goes to EDT, or vice versa):
Table: TimeZone
Fields: TimeZone, Offset
Values: EST, -4
--Multiply by -1, since we're converting EST to GMT.
--Offsets are to go from GMT to EST.
SELECT #activityGmtBegin = DATEADD(hh, Offset * -1, #activityDateMidnight)
FROM TimeZone
WHERE TimeZone = #activityDateTZ
which should give you '1/1/2008 4:00 AM'. Then, you can just search in GMT:
SELECT * FROM EventTable
WHERE
EventTime >= #activityGmtBegin --1/1/2008 4:00 AM
AND EventTime < (#activityGmtBegin + 1) --1/2/2008 4:00 AM
The event in question is stored with a GMT EventTime of 1/2/2008 3:00 AM. You don't even need the TimeZone in the EventTable (for this purpose, at least).
Since EventTime is not in a function, this is a straight index scan - which should be pretty efficient. Make EventTime your clustered index, and it'll fly. ;)
Personally, I'd have the app convert the search time into GMT before running the query.
You're spoilt for choice in terms of options here. If you are using Sybase or SQL Server 2008 you can create variables of type date and assign them your datetime values. The database engine gets rid of the time for you. Here's a quick and dirty test to illustrate (Code is in Sybase dialect):
declare #date1 date
declare #date2 date
set #date1='2008-1-1 10:00'
set #date2='2008-1-1 22:00'
if #date1=#date2
print 'Equal'
else
print 'Not equal'
For SQL 2005 and earlier what you can do is convert the date to a varchar in a format that does not have the time component. For instance the following returns 2008.08.22
select convert(varchar,'2008-08-22 18:11:14.133',102)
The 102 part specifies the formatting (Books online can list for you all the available formats)
So, what you can do is write a function that takes a datetime and extracts the date element and discards the time. Like so:
create function MakeDate (#InputDate datetime) returns datetime as
begin
return cast(convert(varchar,#InputDate,102) as datetime);
end
You can then use the function for companions
Select * from Orders where dbo.MakeDate(OrderDate) = dbo.MakeDate(DeliveryDate)
Eric Z Beard:
the activity date is meant to indicate the local time zone, but not a specific one
Okay - back to the drawing board. Try this:
where t.TheDateINeedToCheck BETWEEN (
dateadd(hh, (tz.Offset + ISNULL(ds.LocalTimeZone, 0)) * -1, #ActivityDate)
AND
dateadd(hh, (tz.Offset + ISNULL(ds.LocalTimeZone, 0)) * -1, (#ActivityDate + 1))
)
which will translate the #ActivityDate to local time, and compare against that. That's your best chance for using an index, though I'm not sure it'll work - you should try it and check the query plan.
The next option would be an indexed view, with an indexed, computed TimeINeedToCheck in local time. Then you just go back to:
where v.TheLocalDateINeedToCheck BETWEEN #ActivityDate AND (#ActivityDate + 1)
which would definitely use the index - though you have a slight overhead on INSERT and UPDATE then.
I would use the dayofyear function of datepart:
Select *
from mytable
where datepart(dy,date1) = datepart(dy,date2)
and
year(date1) = year(date2) --assuming you want the same year too
See the datepart reference here.
Regarding timezones, yet one more reason to store all dates in a single timezone (preferably UTC). Anyway, I think the answers using datediff, datepart and the different built-in date functions are your best bet.