When casting a datetime as date, why does SQLite3 only return the year and not the full date? - sqlite

I know that you can cast a datetime to date using the date() function:
sqlite> select date('2000-01-01 10:00:00');
2000-01-01
But why does SQLite3's cast expression such as in
sqlite> select cast('2000-01-01 10:00:00' as date);
2000
only return the year?
Even using an explicit datetime() setup solely returns the year:
sqlite> select cast(datetime('2000-01-01 10:00:00') as date);
2000
Or:
sqlite> select cast(datetime('now') as date);
2019
Looking at Postgresql, it resolves both properly:
postgresql> select date('2000-01-01 10:00:00');
2000-01-01
postgresql> select cast('2000-01-01 10:00:00' as date);
2000-01-01
What's the technical explanation for SQLite3's – to me unexpected – behavior?

For SQLite there is no Date datatype. As mentioned in their documentation here: https://www.sqlite.org/datatype3.html
What you use as Date is actually TEXT.
You can check that:
select typeof(datetime('now'));
returns:
text
And:
select typeof(cast(datetime('now') as date));
returns:
integer
So the result of cast('2000-01-01 10:00:00' as date) is an integer and it's the same
integer that you get by:
select '2000-01-01 10:00:00' + 0
when SQLite implicitly converts '2000-01-01 10:00:00' to 2000 in order to use it in a mathematical operation.
In the case of dates it happens to be the numeric value of the year, but in general SQLite returns the longest substring of the TEXT, starting from the 1st character, that can be represented as an integer.
So for '2000-01-01 10:00:00' it's the substring until the 1st -, which is the year.

Related

How to do less than equal to for date in sqlite

When I try to run the below query I get no result even though the date time is same as that in the table.
The BillDateTime column is of TEXT Data type
SELECT * FROM BillingTransaction WHERE BillDateTime <= datetime('2021-09-19 07:21:31.371766')
BillNo
VechicleNo
BillDateTime
LoadType
BillAmount
FirstWeight
SecondWeight
1
ka04sdfl
2021-09-19 07:21:31.371766
EMPTY
30
400
0
The function datetime() strips off everything after the seconds, because it is equivalent to:
strftime('%Y-%m-%d %H:%M:%S', ...)
The result of:
SELECT datetime('2021-09-19 07:21:31.371766')
is:
2021-09-19 07:21:31
So your code is equivalent to:
SELECT * FROM BillingTransaction WHERE BillDateTime <= '2021-09-19 07:21:31'
and this is why you don't get any rows.
You don't need the function datetime(), because the values of the column BillDateTime are strings in the proper ISO format.
You can do direct comparisons with them:
SELECT *
FROM BillingTransaction
WHERE BillDateTime <= '2021-09-19 07:21:31.371766'

I have Year & Month but need to incorpate month number also

This is my value in the table : FY20 JAN
And i am looking for 'FY20 (M01) JAN'. How can convert like this in Oracle 11g SQL query ?
First you convert your string to a value of DATE type. Anything enclosed in double quotes is somewhat hard coded and TO_DATE function ignores them as long as they match the characters in the input in their specific locations. Here FY are in location (index) 1 and 2.
alter session set nls_date_format = 'yyyy-mm-dd';
select to_date('FY20 JAN', '"FY"yy MON') d from dual;
D
----------
2020-01-01
Then, you apply another function TO_CHAR to the date value we got above to get the desired output.
select to_char(
to_date('FY20 JAN', '"FY"YY MON')
, '"FY"yy "(M"mm")" MON'
) c from dual;
C
-----------------------
FY20 (M01) JAN

Convert string to date with date and time together in Hive

I need convert string to datetime (date and time together).
I try this:
cast(to_date(from_unixtime(unix_timestamp('20190303164305', 'yyyyMMddHHmmss'))) as date) as date_data_chamada
timezone: Brazil
But this way returns just date, like this: 2019-03-03, and I need: 2019-03-03 16:43:05
Thanks!
Full code:
INSERT INTO p_b.este PARTITION (dt_originacao_fcdr)
SELECT
tp_registro_fcdr,
seq_registro_fcdr,
tp_cdr_fcdr,
dt_atendimento_fcdr,
data_atendimento_completa_fcdr,
cast(from_unixtime(unix_timestamp(data_atendimento_completa_fcdr, 'yyyyMMddHHmmss'),"yyyy-MM-dd HH:mm:ss")as timestamp) as date_data_atendimento_fcdr,
hr_atendimento_fcdr,
duracao_atend_fcdr,
hr_originacao_fcdr,
duracao_total_fcdr,
duracao_chamada_tarifada_fcdr,
st_chamada_fcdr,
fim_sel_orig_fcdr
FROM p_b.norm;
Remove date casting and to_date functions as you are expecting timestamp!
Example:
hive> select from_unixtime(unix_timestamp('20190303164305', 'yyyyMMddHHmmss'),"yyyy-MM-dd HH:mm:ss") as date_data_chamada;
RESULT:
2019-03-03 16:43:05
If you use to_date or cast('string' as date) then hive results only date(yyyy-MM-dd)!
Ex:
hive> select to_date(from_unixtime(unix_timestamp('20190303164305', 'yyyyMMddHHmmss'),"yyyy-MM-dd HH:mm:ss")) as date_data_chamada;
--2019-03-03
Pass the second argument format string to from_unixtime. Note that the returned type is string.
from_unixtime(unix_timestamp('20190303164305','yyyyMMddHHmmss'),'yyyy-MM-dd HH:mm:ss')

Select data based on month and year

We storing date as String in column created_at by below format 2019-10-09T15:29:28.000+08:00 in Moor.
We would like to write a select query, to retrieve data where month are October and year is 2019.
Future<ABC> selectReadingBasedOnMonth(
int month, int year) {
return (select(abcs)
..where((t) {
final sqliteDate = FunctionCallExpression<DateTime, DateTimeType>(
'date', [t.createdAt]);
return sqliteDate.year.equals(year) &
sqliteDate.month.equals(month);
}))
.getSingle();
}
But we are not getting any data. This is the query displayed in log
I/flutter (12004): Moor: Sent SELECT * FROM abcs WHERE
(CAST(strftime("%Y", date(created_at), "unixepoch") AS INTEGER)) = ?
AND (CAST(strftime("%m", date(created_at), "unixepoch") AS INTEGER)) =
?; with args [2019, 10]
The unixepoch modifier can only be used with date/time strings that are solely digits.
The "unixepoch" modifier (11) only works if it immediately follows a
timestring in the DDDDDDDDDD format.
This modifier causes the
DDDDDDDDDD to be interpreted not as a Julian day number as it normally
would be, but as Unix Time - the number of seconds since 1970.
If the
"unixepoch" modifier does not follow a timestring of the form
DDDDDDDDDD which expresses the number of seconds since 1970 or if
other modifiers separate the "unixepoch" modifier from prior
DDDDDDDDDD then the behavior is undefined.
For SQLite versions before
3.16.0 (2017-01-02), the "unixepoch" modifier only works for dates between 0000-01-01 00:00:00 and 5352-11-01 10:52:47 (unix times of
-62167219200 through 106751991167).
Date And Time Functions
For example consider the following (based upon your query) :-
DROP TABLE IF EXISTS abcs;
CREATE TABLE IF NOT EXISTS abcs (created_at TEXT);
INSERT INTO abcs VALUES ('2019-10-09T15:29:28.000+08:00');
SELECT *,
CAST(strftime('%Y', date(created_at)/*, 'unixepoch'*/) AS INTEGER) AS year_nounixepoch,
CAST(strftime('%m', date(created_at)/*, 'unixepoch'*/) AS INTEGER) AS month_nounixepoch,
CAST(strftime('%Y', date(created_at), 'unixepoch') AS INTEGER) AS year_invalid,
CAST(strftime('%m', date(created_at), 'unixepoch') AS INTEGER) AS month_invalid,
CAST(strftime('%Y', strftime('%s',date(created_at)), 'unixepoch') AS INTEGER) AS year_unixepoch,
CAST(strftime('%m', strftime('%s',date(created_at)), 'unixepoch') AS INTEGER) AS month_unixepoch
FROM abcs
WHERE CAST(strftime('%Y', strftime('%s',date(created_at)), 'unixepoch') AS INTEGER) = 2019 AND CAST(strftime('%m', strftime('%s',date(created_at)), 'unixepoch') AS INTEGER) = 10;
DROP TABLE IF EXISTS abcs; /* cleanup test environment */
Note that single quotes have been used to replace double quotes, which would be the correct SQL although this discrepancy may be due to how the message is output.
This results in :-
i.e. where the unixepoch modifier has been used it results in null as the date/time is not solely digits.
the selection criteria, with unixepoch via strftime('%s',..... works as expected.
Thanks for the answer provided by simolus3
final asDate = FunctionCallExpression('date', [t.createdAt]);
final year = FunctionCallExpression<String, StringType>(
'strftime', [const Constant<String, StringType>('%Y'), asDate]);
final month = FunctionCallExpression<String, StringType>(
'strftime', [const Constant<String, StringType>('%m'), asDate]);
return year.equals('2019') & month.equals('07');

List the details of the senior employee belongs to a certain year

I wish to obtain in sqlite :
List the details of the senior employee belongs to 1981
But the
select * from emp where hiredate in (select min(hiredate) from emp
where to_char( hiredate,’YYYY’) = ‘1981’)
not working. I suppose the to_char function is not recognized.
I've tried
select min(hiredate) from table
where hiredate IN ('1981%')
result NULL
I mention the date is in the sqlite supported format ; yyyy-mm-dd
Thank you in advance! :))))
I assume that the hiredate's format is YYYY-MM-DD since this is the only format that is directly comparable and can be manipulated as a date in SQLite (although it is actually TEXT).
If so, then use LIKE operator like this:
select * from emp
where hiredate = (select min(hiredate) from emp where hiredate like '1981%')
If you want the earliest hire date in 1981, just use
SELECT *
FROM emp
WHERE hiredate LIKE '1981-%'
ORDER BY hiredate
LIMIT 1;
which sorts all the rows with 1981 hire dates by that date and only returns the first (minimum) one.
Instead of to_char () you can use the strftime function.
strftime ('% Y', hiredate)
SELECT MIN(hiredate) FROM table WHERE STRFTIME ('% Y', hiredate) = '1981'

Resources