I have a varchar field that stores a duration for connections that occasionally goes into the days. I'm trying to separate the total number of days from the hh:mm:ss in this field so I can store them separately but I'm getting an out of range error whenever I try to convert this data to any type of datetime variation in order to datepart the days from the value and then deduct. Is their any way of doing this or will I need to resort to a crude charindex(':' just to remove the days?
You'll have to chop it up since it's not in a valid date or time format:
DECLARE #timeString VARCHAR(50) = '114:48:50'
SELECT Day_CT = LEFT(#timeString ,CHARINDEX(':',#timeString )-1)/24
,Tm = CAST(CAST(LEFT(#timeString ,CHARINDEX(':',#timeString )-1)%24 AS VARCHAR(12))+STUFF(#timeString ,1,CHARINDEX(':',#timeString )-1,'') AS TIME)
This is one of the many reasons why dates and times shouldn't be stored in string data types, it makes using them ugly.
Related
I need to get all the values from a SQL Server database by day (24 hours). I have timestamps column in TestAllData table and I want to select the data which only corresponds to a specific day.
For instance, there are timestamps of DateTime type like '2019-03-19 12:26:03.002', '2019-03-19 17:31:09.024' and '2019-04-10 14:45:12.015' so I want to load the data for the day 2019-03-19 and separately for the day 2019-04-10. Basically, it is needed to get DateTime values with the same date.
Is this possible to use some functions like DatePart or DateDiff for that?
And how can I solve such problem overall?
As in this case, I do not know the exact difference in hours between a timestamp and the end of the day (because there are various timestamps for 1 day) and I need to extract the day itself from the timestamp. After that, I need to group the data by days or something like this and get block by block. For example:
'2019-03-19' - 1200 records
'2019-04-10' - 3500 records
'2019-05-12' - 10000 records and so on
I'm looking for a more generic solution not supplying a timestamp (like '2019-03-19') as a boundary or in a where clause because the problem is not about simply filtering the data by some date!!
UPDATE: In my dataset, I have about 1,000,000 records and more than 100 unique dates. I was thinking about extracting the set of unique dates and then kind of run a query in the loop where the data would be filtered by the provided day. It would look in such a way:
select * from TestAllData where dayColumn = '2019-03-19'
select * from TestAllData where dayColumn = '2019-04-10'
select * from TestAllData where dayColumn = '2019-05-12'
...
I might use this query in my code, so I may run it in the loop from Scala function. However, I am not sure that in terms of performance it would be ok to run separate unique dates extraction query.
Depending on whether you want to be able to work with all the dates (rather than just a subset), one of the easiest ways to achieve this is with a cast:
;with cte as (SELECT cast(my_datetime as date) as my_date, * from TestAllData)
SELECT * FROM cte where my_date = '2019-02-14'
Note when casting datetime to date, times are truncated, ie just the date part is extracted.
As I say though, whether this is efficient, depends on your needs, as all datetime values from all records will be cast to date, before the data is filtered. If you want to select several dates (as opposed to just one or two), however, it may prove overall quicker, as it reads the whole table once and then gives you a column upon which you can much more efficiently filter.
If this is a permanent requirement, though, I would probably use a persisted computed column, which effectively would mean that the casting is done once initially and then only again if the corresponding value changed. For a large table I would also strongly consider an index on the computed column.
I am trying to make a simple scatter plot in MATLAB with time on the x-axis and wind speed on the y-axis. I loaded in my data from a text file as a table and then tried to use table2array to plot since it needs numeric values not table data. I also tried using double and got another error.
Error Message: Error using scatter (line 55) Input arguments must be numeric or objects which can be converted to double.
Error in windconversions (line 18) scatter(time,wnd_TS)
I'm not sure if having the times as strings will also be an issue.
T = readtable('allunderway.txt', 'HeaderLines', 2);
%A = table2array(T)
date = T(:,1);
time = T(:,2);
wnd_TD = T(:,10);
wnd_TS = T(:,11);
table2array(wnd_TS);
table2array(time);
%double(wnd_TS);
scatter(time,wnd_TS)
A simpler way to access the data contained within the table is to use the dot notation, as T.VarN, where N is the number of the column you are interested in.
In your code you are using only 'time' for the plot, however this consists of hours, minutes and seconds only. I suspect that for your graphical analysis you require the combination of both the date and the hours.
It is possible to perform arithmetic addition on datetimes, however it is required that the two variables have the same format. By converting both dates to format 'MM/dd/yyyy HH:mm:SS' you are actually modifying the data of the variables. However, as stated in the documentation:
Since the data in the first column of the file ("date") have no time information, the time of the resulting datetime values default to midnight. Since the data in the second column of the file ("time") have no associated date, the date of the datetime values defaults to the current date.
When you add the variables date and time together together, you can add the date ('MM/dd/yyyy') of date to the time ('HH:mm:SS') of time.
An example of datetime conversion and addition follows.
Variables date and time before conversion:
date = 05/04/2011
time = 00:00:42
After conversion:
date = 05/04/2011 00:00:00
time = 06/01/2018 00:00:42
Adding the two:
05/04/2011 00:00:42
The code which reads the table and plots the scatter graph:
%Read table.
T = readtable('allunderway.txt', 'HeaderLines', 2);
%Access data of interest from table.
date = T.Var1;
time = T.Var2;
wnd_TS = T.Var11;
%Convert variable time to datetime.
time = datetime(time,'Format','HH:mm:SS');
%Add hours, minutes and seconds to variable date.
date = datetime(date,'Format','MM/dd/yyyy HH:mm:SS');
%Add month, day and year to variable time.
time = datetime(time,'Format','MM/dd/yyyy HH:mm:SS');
%Combine date and time variables.
fullt = date+timeofday(time);
scatter(fullt,wnd_TS);
The output of the code is the required scatter graph:
You can find more information on combining date and time from separate variables here.
Why do so much extra work. You could have simply used scatter(datenum(T.time),T.wnd_TS). That should do the job and save all the extra effort.
I would like to keep my dates as datetime datatype by also be in MM/DD/YYYY format. I know how to do this by converting them to a varchar, but want to keep the datetime format. Can anyone help with this?
Currently I have tried
SELECT CONVERT(datetime, GETDATE(), 101)
which is not working...
There is a basic misunderstanding in your question. Repeat after me: Datetimes don't have a format.
It helps if you think of them as just an array of seven integers (year, month, day, hours, minutes, seconds, milliseconds) with certain constraints. That's not in any way accurate, but it helps to get the notion out of your head that something akin to 12/31/2015 is stored in your database.
Datetimes only get a format when (implicitly or explicitly) being converted to strings. You already know how to set the format when explicitly converting to string, now all that is left to do is to find the implicit conversion that is obviously bothering you and replace it with an explicit one.
Date and datetime Values stored in the database are NOT in any recognizable format. They are stored in binary (1s and 0s) in a proprietary format where one part represents the number of days since a defined reference date (1 jan 1900) in SQL server). and the other part represents the time portion of the value. (in sql server, its the number of 1/300ths of a second since midnight.)
ALL formatting of dates and date times, no matter what format you wish for, is done only after the values have been extracted from the database, before you see them on screen, in whatever application you are using.
You can find all the formats that the SQL Server convert function can use on this MSDN Convert Link
I need to add time entries from a table. The time entries are stored as
P2H30M (2 Hours 30 Minutes)
What would be the best way to go about this?
Are you adding time intervals to other time intervals? Or time intervals to another column that's defined as a datetime?
Either way, you'd want to create a function to convert those values to an integer (minutes) and then add the integers together and use another function to convert them back to your proprietary character format.
If you're wanting to add them to a datetime column you could then use:
UPDATE YourTable
SET YourDateTimeCol = DATEADD(MI, YourDateTimeCol, <yourminuteinteger>)
WHERE <whatever your where clause would be>
I am trying to insert a time only value, but get the following error
ex {"SqlDateTime overflow. Must be between 1/1/1753 12:00:00 AM and 12/31/9999 11:59:59 PM."} System.Exception
From the front end, the time is selected using the "TimeEdit" control, with the up and down arrows. The table in SQL Server has the fields set as smalldatetime. I only need to store the time. I use the following to return data to the app
select id,CONVERT(CHAR(5),timeFrom,8)as timeFrom,CONVERT(CHAR(5),timeTo,8)as timeTo
FROM dbo.Availability
where id = #id
and dayName = #weekday
How do I pass time only to the table?
Edit ~ Solution
As per Euardo and Chris, my solution was to pass a datetime string instead of a time only string. I formatted my result as per Time Format using "g".
Thanks
You can set the date to 1/1/1753 wich is date min value for datetime in MSSQL and then add the hour you want to store. Of course you have to consider this every time you need to get the value, but you can wrap that with some helpers.
Or you can use MSSQL 2008 and use the new TIME datatype.
Pick a date that is in the range(ie, 1/1/1970) and use it for everything you insert.
If you are only keeping track of the time, think about storing it in an int as an offset from midnight in whatever granualarity you need (seconds, minutes, hours, ...). You can then convert it to a TimeSpan in your code using the appropriate TimeSpan.From??() method. To go back the other way, you can use TimeSpan.Total?? and truncate if need be. If you need to do manual queries you can write a SQL function that will convert hours/mins/seconds to the equivalent offset.
I prefer this over using a datetime and picking an arbitrary day as it makes the purpose of the field clearer, which reduces confusion.
there is no such thing as Time in SQL, there is only DateTime.
For your purpose, I would use something like this to only return the time portion.
SELECT (GETDATE() - (CAST(FLOOR(CAST(GETDATE() as FLOAT)) AS DateTime)))
where GETDATE() is the datetime you want to filter.
When setting the time in the database, you will have to add '01/01/1901' or '01/01/1753' to the time.
Dont use CAST and Convert to varchar when working with datetime, its slow. Stick to floating numerical operations.