Casting negative integer to DATE in SQL - mysql

I'm having a problem working with a Navicat Database. I got a column in SQL called fechaNacimiento (Birthdate) that should be a Date type, but instead it's stored as integers (most negative integers):
SELECT fechaNacimiento FROM Registrados
And I'm getting:
fechaNacimiento
-1451678400
-2082829392
-1798746192
-1199221200
-1356984000
-694299600
-1483214400
-1924976592
-1830368592
-2019670992
-1678909392
239252400
1451617200
-879541200
I don't know how this dates where loaded, I just know that inside that negative integer there's a date, and nobody here have any clue about how to spell SQL, so I have nobodoy to ask. If I just cast it to DATETIME, I get all of them as NULL values. Any idea in how to convert this data to Date type?

Numbers like that make me think of Unix times, number of seconds since 1970. If so, you might be able to do:
select dateadd(second, <column>, '1970-01-01')
This would put the negative values sometime before 1970 (for instance, -1678909392 is 1916-10-19). If you have older dates, then that might be the format being used.
These might also be represented as milliseconds. If so:
select dateadd(second, <column>/1000, '1970-01-01')
In this case, -1678909392 represents 1969-12-12.
In MySQL, you would use:
select '1970-01-01' + interval floor(column / 1000) second

Related

Difference between two dates in MySQL with DATE() function

I am using DATE() function to calculate the difference between two dates in MySQL
value of SYSDATE() function is following
select SYSDATE();
2020-07-15 12:16:07.0
When I am using date from same month, it is giving correct result
select DATE(SYSDATE())- DATE('2020-07-13');
2
But when I am using date from last month it is giving difference as 86 instead of 16;
select DATE(SYSDATE())- DATE('2020-06-29');
86
Edit:
I am aware that we can use DATEDIFF() but I want to verify why DATE() function is giving results like this since we are already using this in code
MySQL doesn't support subtracting one date from another. The code
SELECT DATE '2020-07-15' - DATE '2020-06-29';
should hence result in an error, but MySQL silently converts this to this instead:
SELECT 20200715 - 20200629;
Seeing that you want to subtract two values, it assumes that you want to work with numbers. Dates are not numbers, but their internal representation yyyymmdd can be represented numerically. So, while CAST(DATE '2020-07-15 ' AS int) fails with a syntax error, as it should, MySQL is not consistent, when it comes to subtraction. It generates the numbers 20200715 and 20200629 and works with these.
I consider this a bug. MySQL should either raise an exception or return an INTERVAL when subtracting one DATE from another.

why i cant return rows between two dates with timestamp correctly

how to return exactly rows between two dates with timestamps
this code didn't return all row between 01-04 and 07-05
so what is the problem and why it didn't work correctly
and how to select rows between two date with timestamp when i use date
format like this 01-04-2015
SELECT d_send_items.si_id ,
DATE_FORMAT(FROM_UNIXTIME(d_send_items.si_send_date), '%d-%m-%Y')
FROM d_send_items WHERE
DATE_FORMAT(FROM_UNIXTIME(d_send_items.si_send_date), '%d-%m-%Y') BETWEEN '01-04-2015' AND '07-05-2015'
date_format returns a string, so between is using string comparisons to figure out whether the values are between those two you provide.
So, unless your date format is something like yyyy-mm-dd, between is not going to work as you expect.
For example, the date 08-04-2015 is between the two dates 01-04-2015 and 07-05-2015 but the string 08-04-2015 is not between the two strings 01-04-2015 and 07-05-2015, because the most significant portion 08 is beyond the range which terminates at 07....
So you could use:
where
date_format(from_unixtime(d_send_items.si_send_date), '%Y-%m-%d')
between '2015-04-01' and '2015-05-07'
but per-row functions never scale well in relational databases.
If they're proper timestamp fields, I think you can also bypass the conversion and use something like:
where d_send_items.si_send_date >= '01-04-2015'
and d_send_items.si_send_date < '08-05-2015'
(noting the < day following bit for the second conditional since 08-05-2015 is the same as 08-05-2015 00:00:00) assuming MySQL will recognise those date formats as dd-mm-yyyy.
However, even if it doesn't and you have to use some function to turn those string into timestamp values, this is something that would be done once for the whole query rather than (most likely) for every single row.

MySQL: Modifying output of a field for calculation

I know calculating age from DOB is relatively simple but I have an issue with different data entry formats in the database. Also, I know this can be easier using PHP, but I don't know PHP and only have MySQL to work with.
The DOB entered into the DB is entered as "month/day/year" or "00/00/0000". But when calculating against today's date, the date would be formatted as "year-month-day" or "0000-00-00". Furthermore, the month placed in the DOB field can have either a one number month (1/01/1999) or a two number month (01/01/1999), so it's not consistent.
I am trying to use the below to utilize CONCAT, SUBSTRING and LOCATE to output the DOB in a better suited format for the age calculation. I think I'm close but not quite there. Any help would be very much appreciated.
SELECT
CONCAT(SUBSTRING(APPU_DOB,-4,4),'-', SUBSTRING(APPU_DOB,LOCATE('/', APPU_DOB),1),'-',SUBSTRING(APPU_DOB,4,2))
FROM APPU_APP_USER
JOIN APPL_APP ON APPU_APPL_ID = APPL_ID
WHERE DATE_FORMAT(APPL_CREATE_DT, '%Y-%M-%D') >= '2014-01-01';
Instead of Concat use str_to_date function.
select str_to_date( appu_dob, '%m/%d/%Y' ) as 'dob';
on 1/01/1999 it returns a valid date formatted object with value 1999-01-01.
You can use it on other date strings that have single or two digit day or month numbers.
Note: To represent or refer a month, use small case m but not capital M, in the format pattern string.
And you should better redefine the data type of appu_dob field to date. So that you can easily apply date specific functions on it for any calculations.

T-SQL Select data from multiple days between certain times

In my table I have minute data about daily temperature measurements. The table looks like:
DateTime timestamp, Float temperature
I would like to have the temperatures on different dates between a certain interval and then only show the temperature between 7am and 8pm.
I know how to get the data between dates:
SELECT [timestamp],[temperature]
FROM [meteo_data]
WHERE [timestamp] BETWEEN '2012-11-10' and '2012-11-17'
How to I implement the time restriction (7am - 8pm) as well?
Thanks a lot!!
If you are on SQL Server 2008 or above, you can use TIME datatype
SELECT [timestamp],[temperature]
FROM [meteo_data]
WHERE [timestamp] BETWEEN '2012-11-10' and '2012-11-17'
AND CONVERT(TIME,[timestamp]) BETWEEN '19:00:00' AND '20:00:00'
EDIT: Also it is recommended to use ISO (yyyymmdd) date format when using date as a string. i.e.
BETWEEN '20121110' and '20121117'
The DateTime and TimeStamp values should contain precision you need, so
SELECT [timestamp],[temperature]
FROM [meteo_data]
WHERE [timestamp] BETWEEN '2012-11-10' and '2012-11-17'
AND RIGHT([timestamp], 12) BETWEEN '19:00:00.000' AND '20:00.00.000'
You may need to adjust how many characters you are evaluating in the RIGHT predicate depending on the precision in your database. But the idea is to take all the parts that constitute the hours, minutes, seconds and miliseconds and restrict that to just those between the hours you require.

How do I get the average time from a series of DateTime columns in SQL Server 2008?

Lets say I have a table that contains the following - id and date (just to keep things simple).
It contains numerous rows.
What would my select query look like to get the average TIME for those rows?
Thanks,
Disclaimer: There may be a much better way to do this.
Notes:
You can't use the AVG() function against a DATETIME/TIME
I am casting DATETIME to DECIMAL( 18, 6 ) which appears to yield a reasonably (+- few milliseconds) precise result.
#1 - Average Date
SELECT
CAST( AVG( CAST( TimeOfInterest AS DECIMAL( 18, 6 ) ) ) AS DATETIME )
FROM dbo.MyTable;
#2 - Average Time - Remove Date Portion, Cast, and then Average
SELECT
CAST( AVG( CAST( TimeOfInterest - CAST( TimeOfInterest AS DATE ) AS DECIMAL( 18, 6 ) ) ) AS DATETIME )
FROM dbo.MyTable;
The second example subtracts the date portion of the DATETIME from itself, leaving only the time portion, which is then cast to a decimal for averaging, and back to a DATETIME for formatting. You would need to strip out the date portion (it's meaningless) and the time portion should represent the average time in the set.
SELECT CAST(AVG(CAST(ReadingDate AS real) - FLOOR(CAST(ReadingDate as real))) AS datetime)
FROM Rbh
I know that, in at least some of the SQL standards, the value expression (the argument to the AVG() function) isn't allowed to be a datetime value or a string value. I haven't read all the SQL standards, but I'd be surprised if that restriction had loosened over the years.
In part, that's because "average" (or arithmetic mean) of 'n' values is defined to be the sum of the values divided by the 'n'. And the expression '01-Jan-2012 08:00' + '03-Mar-2012 07:53' doesn't make any sense. Neither does '01-Jan-2012 08:00' / 3.
Microsoft products have a history of playing fast and loose with SQL by exposing the internal representation of their date and time data types. Dennis Ritchie would have called this "an unwarranted chumminess with the implementation."
In earlier versions of Microsoft Access (and maybe in current versions, too), you could multiply the date '01-Jan-2012' by the date '03-Mar-2012' and get an actual return value, presumably in units of square dates.
If your dbms supports the "interval" data type, then taking the average is straightforward, and does what you'd expect. (SQL Server doesn't support interval data types.)
create table test (
n interval hour to minute
);
insert into test values
('1:00'),
('1:30'),
('2:00');
select avg(n)
from test;
avg (interval)
--
01:30:00