Redshift Query BETWEEN returns nothing - sql

Here's the query that returns nothing:
select TOP 10 *
from table
WHERE 'date' BETWEEN '2018-05-01' AND '2018-05-04'
ORDER BY "date";
Nothing is returned.
The following returns 10 rows:
select TOP 10 *
from table
WHERE 'date' = '2018-05-01'
BTW, the date column is TIMESTAMP.
Any thoughts?

Your where clause is always false, because in English it’s:
where the string 'date' is between the string '2018-05-01' and the string '2018-05-04'
which is false.
Change 'date' to "date". You’ll then be comparing the date column (and the date literals will be automatically cast from text to date).

Works fine for me...
CREATE TABLE stackoverflow (foo TIMESTAMP);
INSERT INTO stackoverflow VALUES (GETDATE());
INSERT INTO stackoverflow VALUES ('2016-01-01 00:11:22'::timestamp);
INSERT INTO stackoverflow VALUES ('2018-01-01 01:02:03'::timestamp);
SELECT * FROM stackoverflow
WHERE foo BETWEEN '2017-02-02' AND '2018-05-04';
Data returned:
2018-01-01 01:02:03
Tip: Be careful when mixing dates and timestamps. A comparison like WHERE date = '2018-05-01' might only find timestamps that are exactly at midnight at the start of that day.

Related

Invalid datetime string when CAST As Date

I have Time column in BigQuery, the values of which look like this: 2020-09-01-07:53:19 it is a STRING format. I need to extract just the date. Desired output: 2020-09-01.
My query:
SELECT
CAST(a.Time AS date) as Date
from `table_a`
The error message is: Invalid datetime string "2020-09-02-02:17:49"
You could also use the parse_datetime(), then convert to a date.
with temp as (select '2020-09-02-02:17:49' as Time)
select
date(parse_datetime('%Y-%m-%d-%T',Time)) as new_date
from temp
How about just taking the left-most 10 characters?
select substr(a.time, 1, 10)
If you want this as a date, then:
select parse_date('%Y-%m-%d', substr(a.time, 1, 10))
select STR_TO_DATE('2020-09-08 00:58:09','%Y-%m-%d') from DUAL;
or to be more specific as your column do as:
select STR_TO_DATE(a.Time,'%Y-%m-%d') from `table_a`;
Note: this format is applicable where mysql is supported

How to select rows by date in sqlite

I have to select all rows from database by just passing date. For example to get all rows that have date 10/23/2012
In sqlite db I store this in DATE column:
01/01/1900 11:00:00 AM
I have tried to get by using date() but I get nothing for date:
select itemId, date(dateColumn) from items
So all I need is to compare only dates but can't find how to do this in sqlite.
Firstly, format your dates to the ISO-8601 standard. Wrap it in Date() to ensure it gets processed as a DATE. Finally, construct your range so that it will include everything from 12:00am onwards until just before 12:00am the next day.
select itemId, dateColumn
from items
where dateColumn >= date('2012-10-23')
AND dateColumn < date('2012-10-23', '+1 day')
SQLite columns are not typed. However, if you compare the column to a DATE as shown, it is sufficient to coerced the column data into dates (null if not coercible) and the comparison will work properly.
Example on SQLFiddle:
create table items (
itemid, datecolumn);
insert into items select
1,'abc' union all select
2,null union all select
3,'10/23/2012 12:23' union all select
4,'10/23/2012' union all select
5,'2012-10-23 12:23' union all select
6,'2012-10-23' union all select
7,'2012-10-24 12:23' union all select
8,'2012-10-24' union all select
9,date('2012-10-24 12:23') union all select
10,date('2012-10-24');
Results:
itemid datecolumn
5 2012-10-23 12:23
6 2012-10-23
Note that although rows 3 and 4 appear to be dates, they are not, because they do not conform to ISO-8601 formatting which is the only format recognized by SQLite.
In SQLite, there is no datatype DATE, it's stored as strings. Therefor, the Strings have to match exactly to be equal.
Since we don't want that, you'll want to "cast" the values from the date-column to pseudo-date and also cast your argument to a pseudo-date, so they can be compared:
SELECT itemId FROM items WHERE date(dateColumn) = date("2012-10-22");
Note that the date-command takes dates formated as YYYY-MM-DD, as further explained in an answer to this older question. The question also shows that you can use the BETWEEN x AND y-command to get dates, matching a range.
SELECT itemId,dateColumn FROM items WHERE dateColumn=date('YYYY-MM-DD HH:MM:SS');
SQLite Reference
select itemId,dateColumn from items
where dateColumn = #date

how to query in sqlite for different date format

I am using sqlite for local database in mobile and in my database, I have date field with column name RN_CREATE_DATE. My RN_CREATE_DATE column value is in this format 'dd-mm-yy HH:MM:SS' and I want to fetch data with given date. What will be the exact query for that I tried with below database column and value
**RN_CREATE_DATE
2012-07-27 11:04:34
2012-05-28 10:04:34
2012-07-22 09:04:34**
SELECT RN_CREATE_DATE
FROM DISPOSITION
WHERE RN_CREATE_DATE=strftime('%Y', '2012-07-28 12:04:34')
but no result found, just help me out with this.
strftime works like this:
sqlite> select strftime('%d-%m-%Y %H:%M:%S', datetime('now'));
2012-09-13 12:42:56
If you want to use it in a WHERE clause, replace datetime('now') with the datetime you want to match in the YYYY-mm-dd HH:MM:SS format.
Example:
SELECT *
FROM t
WHERE c = strftime('%d-%m-%Y %H:%M:%S', '2012-09-13 12:44:22');
-- dd-mm-YYYY HH:MM:SS YYYY-mm-dd HH:MM:SS
I'd like to add some information about using SQLite Date and Time with UNIX epoch time:
The UNIX epoch was 00:00:00 1970-01-01, i.e. midnight of 1st Jan 1970. The current time on UNIX machines (like those running Linux) is measured in seconds since that time.
SQLite has support for this epoch time, and I've found it very useful for using it as the format for a DateTime field in SQLite.
Concretely, suppose I want to have an Event table, for events like concerts etc. I want a fromDateTime field to store when the event starts. I can do that by setting the fromDateTime filed to type INTEGER, as such:
CREATE TABLE IF NOT EXISTS Event(
eventID INTEGER PRIMARY KEY,
name TEXT,
ratingOutOf10 REAL,
numberOfRatings INTEGER,
category TEXT,
venue TEXT,
fromDateTime INTEGER,
description TEXT,
pricesList TEXT,
termsAndConditions TEXT
);
Now, let's get to the usage of the UNIX epoch with SQLite DateTime fields:
Basic
select strftime('%s', '2016-01-01 00:10:11'); --returns 1451607012
select datetime(1451607012, 'unixepoch'); --returns 2016-01-01 00:10:11
select datetime(1451607012, 'unixepoch', 'localtime'); --returns 2016-01-01 05:40:11 i.e. local time (in India, this is +5:30).
Only dates and/or times:
select strftime('%s', '2016-01-01'); --returns 1451606400
select strftime('%s', '2016-01-01 16:00'); --returns 1451664000
select date(-11168899200, 'unixepoch'); --returns 1616-01-27
select time(-11168899200, 'unixepoch'); --returns 08:00:00
Other stuff:
select strftime('%d-%m-%Y %H:%M:%S', '2012-09-13 12:44:22') --returns 13-09-2012 12:44:22
Now, here's an example usage of the above with our Event table:
EXAMPLE:
insert into Event
(name, ratingOutOf10, numberOfRatings, category, venue, fromDateTime, description, pricesList, termsAndConditions)
VALUES
('Disco', '3.4', '45', 'Adventure; Music;', 'Bombay Hall', strftime('%s','2016-01-27 20:30:50'), 'A dance party', 'Normal: Rs. 50', 'Items lost will not be the concern of the venue host.');
insert into Event
(name, ratingOutOf10, numberOfRatings, category, venue, fromDateTime, description, pricesList, termsAndConditions)
VALUES
('Trekking', '4.1', '100', 'Outdoors;', 'Sanjay Gandhi National Park', strftime('%s','2016-01-27 08:30'), 'A trek through the wilderness', 'Normal: Rs. 0', 'You must be 18 or more and sign a release.');
select * from event where fromDateTime > strftime('%s','2016-01-27 20:30:49');
I like this solution because it's really easy to work with programming languages, without too much thinking of the various formats involved in SQLite's DATE, TIME, DATETIME, etc. data types.
strftime always generates four-digit years, so you have to use substr to cut off the first two digits:
... WHERE RN_CREATE_DATE = strftime('dd-mm-', '2012-07-28 12:04:34') ||
substr(strftime('%Y %H:%M:%S', '2012-07-28 12:04:34'), 3)
It would be easier to store the column values in a format that is directly understood by SQLite.
strftime('%Y', '2012-07-28 12:04:34') returns 2012, as:
sqlite> select strftime('%Y', '2012-07-28 12:04:34');
2012
but the RN_CREATE_DATE is of type datetime, which expect a full datetime like '2012-07-28 12:04:34'. what you want might be simply:
SELECT RN_CREATE_DATE
FROM DISPOSITION
WHERE RN_CREATE_DATE='2012-07-28 12:04:34'

How do I match an entire day to a datetime field?

I have a table for matches. The table has a column named matchdate, which is a datetime field.
If I have 3 matches on 2011-12-01:
2011-12-01 12:00:00
2011-12-01 13:25:00
2011-12-01 16:00:00
How do I query that? How do I query all matches on 1 single date?
I have looked at date_trunc(), to_char(), etc.
Isn't there some "select * where datetime in date" function?
Cast your timestamp value to date if you want simple syntax. Like this:
SELECT *
FROM tbl
WHERE timestamp_col::date = '2011-12-01'; -- date literal
However, with big tables this will be faster:
SELECT *
FROM tbl
WHERE timestamp_col >= '2011-12-01 0:0' -- timestamp literal
AND timestamp_col < '2011-12-02 0:0';
Reason: the second query does not have to transform every single value in the table and can utilize a simple index on the timestamp column. The expression is sargable.
Note excluded the upper bound (< instead of <=) for a correct selection.
You can make up for that by creating an index on an expression like this:
CREATE INDEX tbl_ts_date_idx ON tbl (cast(timestamp_col AS date));
Then the first version of the query will be as fast as it gets.
not sure if i am missing something obvious here, but i think you can just
select * from table where date_trunc('day', ts) = '2011-12-01';
Just use the SQL BETWEEN function like so:
SELECT * FROM table WHERE date BETWEEN '2011-12-01' AND '2011-12-02'
You may need to include times in the date literals, but this should include the lover limit and exclude the upper.
From rails I believe you can do:
.where(:between => '2011-12-01'..'2011-12-02')

select statement using Between with datetime type does not retrieve all fields?

I'm facing a strange query result and I want to ask you why I'm facing this issue.
I store some datetime data into TestTable as following :
creation_time
-----------------------
2010-07-10 00:01:43.000
2010-07-11 00:01:43.000
2010-07-12 00:01:43.000
This table is created and filled as following :
create table TestTable(creation_time datetime);
Insert into TestTable values('2010-07-10 00:01:43.000');
Insert into TestTable values('2010-07-11 00:01:43.000');
Insert into TestTable values('2010-07-12 00:01:43.000');
when I execute this query , I get two rows only instead of three as I expected:
SELECT * FROM TestTable
WHERE creation_time BETWEEN CONVERT(VARCHAR(10),'2010-07-10',111) -- remove time part
and CONVERT(VARCHAR(10),'2010-07-12',111) -- remove time part
Or if I execute this query , the same issue ..
SELECT * FROM TestTable
WHERE CONVERT(datetime,creation_time,111) BETWEEN CONVERT(VARCHAR(10),'2010-07-10',111) -- remove time part
and CONVERT(VARCHAR(10),'2010-07-12',111) -- remove time part
My Question :
Why the last row ('2010-07-12 00:01:43.000') does not appear in
the result even if I set the date range to cover all the day from 2010-07-10 to 2010-07-12?
I use Sql server 2005 express edition with windows xp 32-bits.
I'm trying to don't use a workaround solution such as increasing the date range to cover additional day to get the days I want.
Thanks .
You need to remove the time part from creation_time as well. Just use the same CONVERT if it works.
Currently you're asking if 2010-07-12 00:01:43.000 is less than 2010-07-12 00:00:00.000, which is not true.
it does not show the date because you have removed the time part, which would make the date equivalent to '2010-07-12 00:00:00.000' and since the last row is greater than this, so it is not displaying in the query results.
Your script should look like this:
SELECT *
FROM TestTable
WHERE creation_time BETWEEN
convert(datetime, convert(char, '2010-07-10', 106))-- remove time part
and **DATEADD**(day, 1, convert(datetime, convert(char, '2010-07-**11**', 106))) -- remove time part and add 1 day
This script will return all between 2010-07-10 00:00:00 and 2010-07-12 00:00:00. Basically this means all items created in 2 days: 2010-07-10 and 2010-07-11.
Converting columns in your table for comparison can be costly and cause indexes to not be used. If you have a million rows in your table and you have an index on creation_time, you will be doing an index scan and converting all million values to a string for comparison.
I find it better to use >= the start date and < (end date + 1 day):
SELECT *
FROM TestTable
WHERE creation_time >= '2010-07-10'
AND creation_time < dateadd(day, 1, '2010-07-12')
And the reason your second one may not work is because format 111 uses slashes ("2010/07/10"), format 120 uses dashes ("2010-07-10"). Your converts aren't doing anything to your start and end date because you are converting a string to varchar, not a date. If you did this, it might work, but I would still recommend not doing the conversion:
SELECT * FROM TestTable
WHERE CONVERT(datetime, creation_time, 111) BETWEEN
CONVERT(VARCHAR(10), CONVERT(datetime, '2010-07-10'), 111) -- remove time part
and CONVERT(VARCHAR(10), CONVERT(datetime, '2010-07-12'), 111) -- remove time part
Date/time inclusive between 7/10/2010 and 7/12/2010:
SELECT * FROM TestTable
WHERE creation_time BETWEEN
CONVERT(VARCHAR,'2010-07-10',101) -- remove time part
and CONVERT(VARCHAR,'2010-07-13',101) -- remove time part