Get days until future event in SQLite - sqlite

Trying to get several things from a SQLite table with names and dates of birth and am having trouble getting the # of days until a person's next birthday. Dates are stored as SQLite's TEXT data type in format '%Y-%m-%d 00:00:00'.
I can get age:
SELECT ((strftime('%s', 'now') - strftime('%s', dob)) / 31536000) AS age
I like this solution for showing the closest birthdays first:
ORDER BY SUBSTR(date('now'), 6) > SUBSTR(dob, 6), SUBSTR(dob, 6) ASC
But I'm breaking my brain over getting the days until the next birthday. My latest attempt is taking the julianday of the substring of the day and month from dob and concatenate it with the current year to compare against julianday() and put in conditionals to take the year change into account, but I haven't worked that out yet and I'm hoping someone has a more elegant solution.

Have made my hideous solution work, so here it is:
SELECT
CASE WHEN
julianday((SUBSTR(date('now'), 1, 5) || SUBSTR(dob, 6, 5))) > julianday('now')
THEN CAST(ROUND(
julianday((SUBSTR(date('now'), 1, 5) || SUBSTR(dob, 6, 5))) - julianday('now'), 0) AS INTEGER)
ELSE CAST(ROUND((
julianday(SUBSTR(date('now'), 1, 5) || '12-31') - julianday('now')) + (
julianday(SUBSTR(date('now'), 1, 5) || SUBSTR(dob, 6, 5)) - julianday(SUBSTR(date('now'), 1, 5) || '01-01')), 0) AS INTEGER)
END
AS dub FROM person;
Will only have to put in another conditional to improve the rounding.

Related

SQlite REPLACE issue

I have a date in the format 'MM/DD/YYYY'. I need the month, day, and year to be separated by : or - for functions like strftime to work in sqlite. I'm attempting to use REPLACE but it won't work on '/'.
Any help is appreciated.
UPDATE table SET date = REPLACE(date,'/','-')
Even if you replace / with -, the date functions of SQLite will not work with your dates.
The only valid date format for SQLite is YYYY-MM-DD.
Update the column date to that format like this:
UPDATE tablename
SET date = SUBSTR(date, -4) || '-' || SUBSTR(date, 1, 2) || '-' || SUBSTR(date, 4, 2);
See the demo.

SQLite3 seems to be ignoring ORDER BY ASC / DESC

I have a database of sports games which includes the date of these these games in the format DD/MM/YYYY (not good I know) and I'm running the command:
SELECT InningsDate FROM Test WHERE InningsPlayer="Player Name" ORDER BY date(InningsDate) DESC
to sort by date of the innings which does sort the database, however it ignores the DESC at the end and will always show the data in the same order regardless of it I put ASC / DESC / nothing at the end.
Any help will be much appreciated.
The format DD/MM/YYYY is not comparable and you should not use it in SQLite which does not support formatting for dates that don't have the format YYYY-MM-DD.
A solution for your case would be:
ORDER BY substr(InningsDate, -4) || substr(InningsDate, 4, 2) || substr(InningsDate, 1, 2) DESC
but as a permanent solution consider changing the format of the dates:
UPDATE Test
SET InningsDate =
substr(InningsDate, -4) || '-' ||
substr(InningsDate, 4, 2) || '-' ||
substr(InningsDate, 1, 2)

How to search in sqlite for hour regardless of timezone?

I wanted to make a database containing my blood sugar levels (I have diabetes).
For each entry, the timestamp of the measurement is saved like this "2020-05-02 12:11:13 +0200".
Now I want to plot the data by the hour (get the same hour of different days).
If I have traveled to a different timezone the entries for this day will be n hours of.
For example, if I want to get all entries for 13:00 I will get the values that were measured at 04:00 in California and 20:00 in Tokyo. But I want the 13:00 o'Clock values from all these places/timezones.
Is this possible, or should I just create a separate column for UTC and local time?
I already tried things like these:
... WHERE strftime('%H', date) = '13'
... WHERE strftime('%H', date,"UTC") = '13'
... WHERE time(date)>= time('00:00:00','+13 hour')
Solution:
See #forpas answer.
I modified it a little
strftime('%H',datetime( substr(date, 1, 19))) = '10'
You need string functions to extract the YYYY-MM-DD hh:mm:ss part of the date and add the offset which may include minutes:
where
strftime(
'%H',
datetime(
substr(date, 1, 19),
substr(date, 21, 3) || ' hour',
substr(date, 21, 1) || substr(date, -2) || ' minute'
)
) = '13'
apparently sqlite doesn't understand the format of your timestamp, because of the timezone format at the end (+0200)
not sure if you must use da date/time function, but you can easily subtract the hour with substr;
... WHERE substr(tm, 12, 2) = '13'

sqlite, how to get the last n records whitout ORDER BY

I need to take the last 7 values of a column I was thinking of using 'LIMIT' but I don't know if it also works in reverse. Take an example, I have these values 1, 2, 3, 4, 5, 6, 7, 8, 9, 10; I need to get 4, 5, 6, 7, 8, 9, 10, considering the fact that in the future other records will be added after 10. Is there a solution with 'LIMIT' or are there other solutions? I can't use ORDER BY 'couse the values i need get are the last 7 days of values and sqlite don't have date type and I don't registered date as milliseconds but i do in date format dd-mm-yyyy so use 'ORDER BY date' don't works. Thanks
If you change the format of the dates to YYYY-MM-DD then it is as simple as this:
SELECT columnname
FROM tablename
ORDER BY date DESC
LIMIT 7
As it is now the date format the only thing that you can do is construct the proper format in the ORDER BY clause with SUBSTR():
SELECT columnname
FROM tablename
ORDER BY SUBSTR(date, 7) || SUBSTR(date, 4, 2) || SUBSTR(date, 1, 2) DESC
LIMIT 7
This expression:
SUBSTR(date, 7) || SUBSTR(date, 4, 2) || SUBSTR(date, 1, 2)
transforms a date like 05-01-2020 to 20200105 so it is comparable and can be used to sort the rows.

SQLite ISO (ie European style) week numbers

I want to return ISO standard week numbers (ie week 1-52/53) from a date.
I have tried using the built in function strftime, but with no success.
Can anyone suggest a way without having to write a custom C or other function.
I know this is an old question, but recently I was looking for an efficient solution for the same problem, and this is what I came up with:
SELECT
my_date,
(strftime('%j', date(my_date, '-3 days', 'weekday 4')) - 1) / 7 + 1 as iso_week
FROM my_table;
The basic idea is to calculate the ISO week number by simply performing integer division of the day of year of the Thursday of the date being looked up (my_date) by 7, giving a result between 0 and 52, and then adding 1 to it. And the subtraction by 1 just before the division is there just for the alignment of the division: Thursday of week 1, for example, can have a day of year between 1 and 7, and we want the result of the division to be 0 in all cases, so we need to subtract 1 from the day of year before dividing it by 7.
What specifically did you try?
This works for me (using built-in SQLite from Python REPL):
import sqlite3
c = sqlite3.connect(':memory:')
c.execute('''create table t (c);''')
c.execute('''insert into t values ('2012-01-01');''')
c.execute('''select c, strftime('%W',c) from t;''').fetchone()
# -> (u'2012-01-01', u'00')
OK, so I managed to answer my own question. For anyone who might need a similar solution, this is what I came up with. Please note, I do not have an IT background and my SQL is self taught.
General process
Get the Thursday of the week the date belongs too.
Get the 4th of January of the year of that Thursday.
Get the Thursday of the week the 4th January date belongs too.
Subtract Step 2 with Step 3, divide by 7 and add 1.
Translated into SQLite....
SELECT
date,
CASE CAST (strftime('%w', wknumjanfourth) AS INTEGER)
WHEN 0 THEN ((JULIANDAY(datesThur) - JULIANDAY(strftime("%s", wknumjanfourth) - 259200, 'unixepoch')) / 7) + 1
ELSE ((JULIANDAY(datesThur) - JULIANDAY(DATE(strftime("%s", wknumjanfourth) - (86400 * (strftime('%w', wknumjanfourth) - 1)), 'unixepoch'), '+3 day')) / 7) + 1
END AS weeknum
FROM
(
SELECT
date,
datesThur,
DATE(datesThur,'start of year','+3 day') AS wknumjanfourth
FROM
(SELECT
date,
CASE CAST (strftime('%w', date) AS INTEGER)
WHEN 0 THEN DATE(strftime("%s", date) - 259200, 'unixepoch')
ELSE DATE(DATE(strftime("%s", date) - (86400 * (strftime('%w', date) - 1)), 'unixepoch'), '+3 day')
END AS datesThur
FROM TEST
))
If anyone can improve this SQL, I would appreciate the feedback.

Resources