SQlite: Select rows within a specific time range, ignoring the date - sqlite

I have a table called messages that stores messages from a chat with the following columns: username, message, datetime, where the type of datetime is TEXT and it is stored in the following format: "yyyy/MM/dd hh:mm:ss". I want to retrieve the average count of rows within a specific time range, without bothering with the date. For instance:
SELECT avg(count(message))
FROM messages
WHERE datetime < "2016/mm/dd 13:00:00" AND
datetime > "2016/mm/dd 12:00:00"
Is there some operator that allows any character to take the place of "mm" and "dd". Essentially, I am trying to construct a query that retrieves the average amount of messages within a specific time range, not the amount of messages on a specific date.

If I read your question correctly, you want to use your WHERE clause to restrict to any calendar date in 2016 between 12 and 13 hours. In this case, you can use STRFTIME to extract the year and hour in string format from your datetime column.
SELECT COUNT(message)
FROM messages
WHERE STRFTIME('%Y', datetime) = '2016' AND
STRFTIME('%H', datetime) < '13' AND
STRFTIME('%H', datetime) > '12'
Note that the reason while the inequalities should work with strings is because numerical strings still sort based on their lexigraphical order.
Update:
Since your datetime column is in a non standard format, you may be able to workaround this by substringing off the various pieces you need to use in the WHERE clause:
SELECT COUNT(message)
FROM messages
WHERE SUBSTR(datetime, 1, 4) = '2016' AND
SUBSTR(datetime, 12, 2) < '13' AND
SUBSTR(datetime, 12, 2) > '12'

Related

Negative dates in sqllite database

I am working locally with an sqllite DB. I have imported some records from teradata where there was a date field in the format of 'YYYY-MM-DD'. When i imported the records the date switched from a date to a number. I know this is a feature of sqllite and that one can access it via date(sqllite_date) when selecting it in a where clause.
My problem is that the dates now appear to be a bit odd. For example the year appears to be negative.
Is there anyway to recover this to the correct format?
Below is an example of converting a number in the database into a date
SELECT date(18386)
# -4662-03-28
SELECT datetime('now')
# 2021-02-11 10:41:52
SELECT date(sqllite_date) FROM mydb
# Returns -4662-03-28
# Should return 2020-05-04
I am very new to this area so apologies if this is a basic question. Thank you very much for your time
In SQLite you can store dates as TEXT, REAL or INTEGER.
It seems that you stored the dates in a column with INTEGER or REAL affinity.
In this case, if you use the function date(), it considers a value like 18386 as a Julian day, meaning the number of days since noon in Greenwich on November 24, 4714 B.C.
This is why date(18386) returns 4662-03-28B.C.
But I suspect that the date values that you have are the number of days since '1970-01-01'.
In this case, 18386 days after '1970-01-01' is '2020-05-04'.
So you can get the dates in the format YYYY-MM-DD if you add the value of your column as days to '1970-01-01':
SELECT date('1970-01-01', datecolumn || ' day') FROM tablename
Or by transforming your date values to seconds and treat them as UNIX time (the number of seconds since '1970-01-01 00:00:00 UTC'):
SELECT date(datecolumn * 24 * 3600, 'unixepoch') FROM tablename
Replace datecolumn with the name of your column.

SQLite strftime() weekday

I have been trying with no success to to count how many values were created in a specific week day:
SELECT count(*) as count FROM packets WHERE strftime("%w", timeIn) = '1';
I have this values in timeIn
1472434822.60033
1472434829.12632
1472434962.34593
I don't know what I am doing wrong here.
furthermore, if I use this:
SELECT count(*) as count FROM packets WHERE strftime("%w", timeIn) = '6';
I get
2
which makes no sense. Thank you in advance.
You appear to be storing the date as the number of seconds since 1970 (the Unix epoch) - a common representation. The time strings accepted by the SQLite date functions (see the Time Strings section) default to interpreting numeric time strings as a Julian day numbers:
Similarly, format 12 is shown with 10 significant digits, but the date/time functions will really accept as many or as few digits as are necessary to represent the Julian day number.
You can see this with the following SELECT:
SELECT strftime('%Y-%m-%d', 1472428800.6) AS t
the result of which is:
4026-48-26
For your date representation to be interpreted as a Unix epoch, you need to include 'unixepoch' in the strftime call:
SELECT strftime('%Y-%m-%d', 1472428800.6, 'unixepoch') AS t
which returns:
2016-08-29
If you modify your SELECT to be:
SELECT count(*) as count FROM packets WHERE strftime("%w", timeIn, 'unixepoch') = '6'
you should see results more inline with your expectations.

How to deal with date in SQLite?

I have a table in Sqlite DB having two fields Id and Date (Date is of type Text).
I have stored a few dates in the table from c#. now i want to get the records matching specific day, month and year.
The query i have tried is:
select strftime('%m', Date) from testTbl Where id = 3;
also:
select Date(substr(Date, 0, 10)) as daa from testTbl Where id = 3;
but the result of these two quires is always null.. can anyone help me to sort this out?
Proposed (immediate) fix
Use the following select
select substr(Date, 0, 10) as daa from testTbl Where id = 3;
Cause of the issue
The problem (if you surround the above substr with a Date function) is that you're using a Text type that is not in the expected format
Time Strings
A time string can be in any of the following formats:
YYYY-MM-DD
YYYY-MM-DD HH:MM
YYYY-MM-DD HH:MM:SS
YYYY-MM-DD HH:MM:SS.SSS
YYYY-MM-DDTHH:MM
YYYY-MM-DDTHH:MM:SS
YYYY-MM-DDTHH:MM:SS.SSS
HH:MM
HH:MM:SS
HH:MM:SS.SSS
now
DDDDDDDDDD
Alternative (better) approach
Anyway IMHO, it would be better to create the column with a Date type and to insert values in the following way
insert into testTbl values (DateTime("2015-12-31"),3);
so that you'll be able to do
SELECT strftime('%m/%d/%Y',Date) from testTbl where id = 3;
or also
SELECT Date from testTbl where Date > DateTime('2016-01-01');
from C# the parameterized command would be similar to
"insert into testTbl values (DateTime(?),?);"
with a parameter value myDate.ToString("yyyy-MM-dd")
Anyway you can actually get the month string with substr(Date,0,2) and the year with substr(Date,5,4) with your current format. I'm simply suggesting an alternative that I would find more standard (using the built-in Date format)

Compare date columns

I need to retrieve the rows that service_date is greater than prod_date.
The data type for prod_date is VARCHAR(10) (2/20/2014 for example) and the data type for service_date is DATE (YYYYMMDD). If I query service_date using "select service_date from service where service_date ='20140201'", the result is showing "2/1/2014" in the result grid. However, it does not work in the query below when I convert service_date to varchar to compare with prod_date. It pulls out all the rows instead of the ones that have greater service_date.
SELECT P.PROD_ID, P.PROD_DESC, S.PROD_ID, S.SERVICE_LOC
FROM PRODUCT P
INNER JOIN SERVICE S
WHERE P.PROD_ID = S.PROD_ID
AND CAST(S.SERVICE_DATE AS VARCHAR(10)) >= P.PROD_DATE
I suggest you use date ordering instead of string/varchar ordering if possible for simplicity and since its [ probably ] closer to what your interested in and less likely to confuse
For example
'01/02/2014' >= '04/01/2013' -- if these are dates or cast to dates
but
'01/02/2014' < '04/01/2013' -- if these are strings
So to keep things simple, it makes sense to cast PROD_DATE to a date when comparing these two fields like :
SELECT P.PROD_ID, P.PROD_DESC, S.PROD_ID, S.SERVICE_LOC
FROM PRODUCT P
INNER JOIN SERVICE S
WHERE P.PROD_ID = S.PROD_ID
AND S.SERVICE_DATE >= cast(P.PROD_DATE as date format 'DD/MM/YYYY')
;
if theres any doubts on prod_dates quality as valid dates can check the conversion on all dates first ( before running/adjusting above )
This isn't 100% error proof given your date is character and could have unexpected values. It does show how you can append a leading 0 to the month value and cast it to a date when the month is determined to be a single digit based on the location of the / in the second position of the PROD_DATE value for a given row.
SELECT CASE WHEN POSITION('/' IN TRIM(P.PROD_DATE)) = 2
THEN CAST('0'|| TRIM(P.PROD_DATE) AS CHAR(10)) AS DATE FORMAT 'MM/DD/YYYY')
ELSE CAST(P.PROD_DATE AS DATE FORMAT 'MM/DD/YYYY')
END AS PROD_DATE_
FROM PRODUCT P;

HP Vertica: partition by TIMESTAMPTZ field

I'm trying to re-partition some table using week number counting from some day:
my_fact table contains a field called time_stamp of type TIMESTAMPTZ
Unfortunately, re-partition doesn't work, and I'm getting the error:
MyDB=> ALTER TABLE my_fact PARTITION BY MOD(TIMESTAMPDIFF('day', time_stamp::TIMESTAMP, TIMESTAMP '2013-09-23'), 156) REORGANIZE;
NOTICE 4954: The new partitioning scheme will produce 12 partitions
ROLLBACK 2552: Cannot use meta function or non-deterministic function in PARTITION BY expression
Should the cast of time_stamp to TIMESTAMP strip any time zone related info from this field thus making it deterministic?
Thanks!
Take a look at the date_part() function, you can use the TIMESTAMPTZ as its source column:
Example :
**The number of the week of the calendar year that the day is in.**
SELECT EXTRACT(WEEK FROM TIMESTAMP '2001-02-16 20:38:40');
Result: 7
SELECT EXTRACT(WEEK FROM DATE '2001-02-16');
Result: 7
Since I got no answer, I'm writing here what I've ended up with:
ALTER TABLE my_fact PARTITION BY
MOD(
TIMESTAMPDIFF(
'day',
'2013-09-23'::timestamptz AT TIME ZONE 'UTC',
time_stamp AT TIME ZONE 'UTC'),
156)
REORGANIZE;
This solution works.

Resources