Excel 5 digit Datetime converted in SQL is 2 days ahead - sql

I have a spreadsheet with Datetimes as follows:
I am importing this file into an application so in Javascript I see the date being brought through as the normal 5 digit datetime code:
So far as I expect... However, when I then try getting this datetime readable in SQL Server, I run the following scripts:
select
CONVERT(varchar(25),cast(28540 as datetime),121),
dateadd(D,28540,0)
And the dates all return PLUS 2 days!
The same happens for all dates I pass through. I could easily just remove 2 from the 5 digit number but I don't want to just do that if there is a rule or reason for this?
Any advice on this is greatly appreciated!

Excel dates are tricky. What they do is count the number of days since Dec 30th, 1899 (and early years are not entirely accurate).
One option is:
dateadd(d, 28540, '1899-12-30')
Demo on DB Fiddle:
select dateadd(d, 28540, '1899-12-30') new_dt
| new_dt |
| :---------------------- |
| 1978-02-19 00:00:00.000 |

Related

Count overnight hours as one day

I have a dataset where certain operations occur during the overnight hours which I'd like to attribute to the day before.
For example, anything happening between 2/23 8pm and 2/24 6am should be included in 2/23's metrics rather than 2/24. Anything from 6:01 am to 7:59pm should be counted in 2/24's metrics.
I've seen a few posts about decrementing time by 6 hours but that doesn't work in this case.
Is there a way to use an If function to specify that midnight-6am should be counted as date-1 rather than date without affecting the metrics for the 6am - 7:59pm hours?
Thanks in advance! Also, a SQL newbie here so apologies if I have lots of followup questions.
You can use date_add with -6 hours and then optionally cast the timestamp as a date.
create table t (dcol datetime);
insert into t values
('2022-02-25 06:01:00'),
('2022-02-25 06:00:00'),
('2022-02-25 05:59:00');
SELECT CAST(DATE_ADD(dcol, INTERVAL -6 HOUR)AS DATE) FROM t;
| CAST(DATE_ADD(dcol, INTERVAL -6 HOUR)AS DATE) |
| :-------------------------------------------- |
| 2022-02-25 |
| 2022-02-25 |
| 2022-02-24 |
db<>fiddle here
As said in the comments, your requirement is the occurrences in a 6 AM to 6 AM day instead of a 12-12 day. You can achieve this by decreasing the time by 6 hours as shown in #Kendle’s answer. Another way to do it is to use an IF condition as shown below. Here, the date is decremented if the time is before 6 AM on each day and the new date is put in a new column.
Query:
SELECT
IF
(TIME(eventTime) <= "06:00:00",
DATE_ADD(DATE(eventTime), INTERVAL -1 DAY),
DATE(eventTime)) AS newEventTime
FROM
`project.dataset.table`
ORDER BY
eventTime;
Output from sample data:
As seen in the output, timestamps before 6 AM are considered for the previous day while the ones after are considered in the current day.

How to get all months between two dates in sql with data

Please suggest a method where in we could retrieve name of all months in between two dates.
The months may or may not contain data, but as the need is to display monthly trend, we are required to fetch all months in between two date ranges with or without data.
The Output will be like:
Jan | Feb | Mar
----------------------
Data | Data| Data
If you use SQL Server, you can use the MONTH() or DATEPART() function to extract the month from a date. For example, the following statement returns the current month in SQL Server: SELECT MONTH(CURRENT_TIMESTAMP); SELECT DATEPART(month, CURRENT_TIMESTAMP);
You could then do a GROUP BY to determine how many events occur per month
In general "dynamic columns" are much harder to achieve than "dynamic rows" so output that looks like the first of the tables below will be easier to achieve than output that looks like the second.
Easier
Month | Data
-------------
Jan | Data
Feb | Data
Mar | Data
Harder
Jan | Feb | Mar
----------------------
Data | Data | Data
In general, the best approach is to have your SQL queries return data in the first type of structure and then if required transform this to the second type in your "presentation layer", which might be in Excel, PowerBI, SSRS, or on a website, for example.
If you have months where there might be no data to be returned, you need some means of generating the months and then outer joining this to the data. Obviously in general, at least behind the scenes you'll want to be including years in your data in addition months as otherwise all the data from Jan 2020 will be grouped together with that from Jan 2021, which is probably not what you want.
Here is a SQL-Server-friendly snippet which will output all the months (and years) between two dates. At the time of writing, you haven't specified a DBMS, so if you aren't on SQL Server, this may not work for you.
DECLARE #datefrom DATE = '2020-06-01'
DECLARE #dateto DATE = '2021-03-01';
WITH cte AS
(
SELECT #datefrom as MyDate
UNION ALL
SELECT DATEADD(month,1,MyDate)
FROM cte
WHERE DATEADD(month,1,MyDate)<=#dateto
)
SELECT
YEAR(cte.MyDate) CalendarYear,
MONTH(cte.MyDate) CalendarMonth,
DATENAME(month, cte.MyDate) as MonthNameFull,
CONVERT(char(3),cte.MyDate,0) as MonthName3Char
FROM
cte
ORDER BY
Year(cte.MyDate),
Month(cte.MyDate)
The final SELECT query could be OUTER JOINed to your actual data to give you your desired results. Pivoting should then be done in the presentation layer.
An alternative to the cte would be to use a "numbers table" and use that to add a number of months to the start date and limit the output to where the result of adding that number of months is between the two provided dates.

How can I calculate the number of minutes per day between a daterange

First off I apologize I do not even know where to start and haven't been able to find anything specific to this particular question.
I have a table with datetimes (start and end) and i need to find a way to get minutes/hours between those days. It could either be a sum of the time on weekdays or a some kind of pivot on each day and grouping by the ID number. I had thought to assign a value to the number of days however the times are random and do not start/end at midnight so I am at a loss as how to approach this.
Here are some examples of the date/time format if that helps.
startdate 2018-12-14 10:53:01
enddate 2018-12-27 11:50:00
Any helps or hints would be greatly appreciated!
Edit
forgot to include I am working in SQL Server (SSMS)
Editing For Additional Clarification
Here is a sample date range with an ID number, I wanted to keep it simple.
|ID number| start time |end time
|1 |12/14/2018 10:53|12/17/2018 12:00
here is what I'm trying to achieve (the separation of each date range/ID #)
ID number| start time |end time |mins|
1 | 12/14/2018 10:53|12/14/2018 23:59|786 |
1 | 12/15/2018 0:00 |12/15/2018 23:59|1439|
1 | 12/16/2018 0:00 |12/16/2018 23:59|1439|
1 | 12/17/2018 0:00 |12/17/2018 12:00|960 |
The MINUTE parameter of the DATEDIFF function can be used to determine the difference in minutes between two datetime columns. As below, the second parameter is the start date and the third parameter is the end date, with the result being the amount of time in the specified interval (days, minutes, etc.) from the start to the end date. If you need to find the number of hours between these two columns the HOUR parameter can be used for this. Grouping can be performed as well, as in the second example.
DATEDIFF:
SELECT DATEDIFF(MINUTE, StartDateColumn, EndDateColumn)
DATEDIFF with Grouping and Aggregation:
SELECT ColumnA, SUM(DATEDIFF(MINUTE, StartDateColumn, EndDateColumn)) as DifferenceInMinutes
FROM YourSchema.YourTable
GROUP BY ColumnA

Storing a time difference in SQL

In my application, I have a database storing a calendar of events:
id | name | date
----+--------------------+--------------------
1 | Birthday Party | 2013-04-27 16:30:00
2 | Dinner Reservation | 2013-03-20 17:00:00
3 | Sunday Brunch | 2013-03-31 11:15:00
When viewing events in the application, users should be able to configure how far in advance from the present moment they wish to view events, stored as a value in the database:
username | datediff
----------+------------------------------------------
user123 | 2 days in advance
goodguy | 93 days in advance
spudly | 365 days in advance
aaaaaa | 17 days, 3 hours, 30 seconds in advance
My question is: what is the best (i.e., most SQL-idiomatic) way to store such a date differential? I could store the time difference as a number in milliseconds, but is there some built-in SQL datatype that is suitable for date differentials, rather than just particular points in time? Is something like DATETIME or TIMESTAMP appropriate for this task?
It must be a relative difference -- for example, for "2 days in advance" I'm not interested in storing a particular date two days in the future, because I'd like the user to see events for the next two days every time he looks at the application.
I'm using Microsoft SQL Server 2008, if it makes any difference.
(This may be a duplicate, but all my search attempts have turned up results about datediff -- which is used to calculate time differences -- but nothing about how best to store time differences.)
Standard SQL has a specific data type for date and time durations: interval. SQL Server doesn't support the interval data type.
DateDiff() returns a signed integer. If you need to store the SQL Server equivalent to a SQL interval, you'll need to store an integer. The integer is a count of the number of datepart boundaries, so you also need to store what kind of datepart boundary the integer refers to. Without the datepart, the signed integer 3 could just as easily mean 3 years or 3 seconds.
As a practical matter, I think I'd rather calculate a timestamp for the reminder, and store that instead of the integer and datepart that define an interval. A timestamp can be indexed and queried much more simply than the integer and datepart. And without the need to support recurring events, I don't see a compelling reason to build a solution more complicated than that.

Help ordering a result by date in SQLite

Is there any way in SQLite to ORDER BY a date, and have result be ordered by time rather than alphabetically?
For example:
SELECT * FROM details GROUP BY date;
John | Smith | April 01, 2011
John | Smith | April 03, 2011
John | Smith | April 04, 2011
John | Smith | March 25, 2011
March should come before April.
I'm guessing that the answer here is to store my dates as long timestamps, however I wasn't sure if it could be done more easily with SQLite.
Thanks!
There isn't a built-in DATE type in SQLite (as exists in some other database management systems), but it does have a nice complement of date and time functions: http://www.sqlite.org/lang_datefunc.html
You can use date("April 01, 2011") to get back an ISO-8601 date (e.g., 2011-04-01).
This format has the advantages of both being a readable string and being sortable. 2011-03-25 naturally comes before 2011-04-01 by standard string comparison rules, so there's no special operation required.
So, store your dates in that format, and get that format using the date() function (or other relevant function).
you can convert date to an actual date in order to compare it.
try to add order by julianday(date) to the end of the query
http://www.sqlite.org/cvstrac/wiki?p=DateAndTimeFunctions
date must be a string and not an actual date. You would need to convert date to an actual date. Here is a link to Sqlite date and time functions.
http://www.sqlite.org/lang_datefunc.html
You can do something like this
select * from sometable order by date(thestringDateColumn)
Hope this helps