Update only the year in SQLite column - sqlite

I have a SQLite3 database that has 366 rows in it, and a date for each day of the year. I need to make sure that the year is current, and if it is not, then I need to update the year to the current calendar year. What I would like to do is something like the following:
UPDATE daily SET date = DATE('%Y', 'now');
or
UPDATE daily SET date = strftime('%Y', 'now');
But those queries just make the date column NULL, and even if they did work as I expected them to, I doubt that it would retain the day and month that is there already.
In MySQL, I can do something like UPDATE daily SET date = ADDDATE(date, INTERVAL 1 YEAR) -- but firstly, it is not a valid SQLite query, and secondly, I need to update to the current year, not just step up one year.
Any help would be appreciated.

Try this:
create table t (id int, d text);
insert into t
select 1, date('2011-01-01') union
select 2, date('2012-03-11') union
select 3, date('2013-05-21') union
select 4, date('2014-07-01') union
select 5, date('2015-11-11');
select * from t;
update t set
d = date(strftime('%Y', date('now')) || strftime('-%m-%d', d));
select * from t;
It uses Date And Time Functions. Firstly it takes month and day from field (strftime('-%m-%d', d)) then add (concatenate) current year (strftime('%Y', date('now'))) and converts it to date.
SQL Fiddle live example.

Related

Incorrect update in Oracle SQL DB

I tried to update a lot of rows in date format ('DD-MON-YY'). S
So, in cases such 22-FEB-99, I got 22th February 1999, instead of 22th February 2099.
Is there a way to specify the year in such cases?
I tried to update a lot of rows in date format ('DD-MON-YY').
If you have a DATE column then that is a binary data type consisting of 7 bytes (representing century, year-of-century, month, day, hour, minute and second); it ALWAYS has those components and it is NEVER stored in any (human-readable) format.
What you probably mean is that your client application (SQL Developer) is displaying the dates in the format DD-MON-RR and it is not showing you the century or time components.
Is there a way to specify the year in such cases?
Rather than letting the client application apply a default format for displaying the date, you can apply an explicit format using TO_CHAR:
SELECT TO_CHAR(your_date_column, 'FMDDth Month YYYY', 'NLS_DATE_LANGUAGE=English')
AS formatted_date
FROM your_table;
Which, for the sample data:
CREATE TABLE your_table (your_date_column) AS
SELECT SYSDATE FROM DUAL UNION ALL
SELECT DATE '2022-01-01' FROM DUAL UNION ALL
SELECT DATE '1970-01-01' FROM DUAL;
Outputs:
FORMATTED_DATE
2nd November 2022
1st January 2022
1st January 1970
in cases such 22-FEB-99, I got 22th February 1999, instead of 22th February 2099.
If you get the value 22th February 1999 then that is because the date is stored as 1999 and not 2099. Note: that a DATE data type always has a century component so the query will display what is stored in the column.
You have probably inserted (or updated) the date as a string:
INSERT INTO your_table (your_date_column)
VALUES('22-FEB-99');
'22-02-99' is not a date data type, it is a string literal. Oracle has tried to be helpful and implicitly convert the date to a string using the NLS_DATE_FORMAT session parameter effectively converting the query to:
INSERT INTO your_table (your_date_column)
VALUES(
TO_DATE(
'22-FEB-99',
(SELECT value FROM NLS_SESSION_PARAMETERS WHERE parameter = 'NLS_DATE_FORMAT')
)
);
However, your NLS_DATE_FORMAT session parameter is set to DD-MON-RR and the RR format model will convert 99 to 1999 and not 2099.
What you need to do is NEVER use implicit conversion from strings to dates; instead:
Use a date literal:
INSERT INTO your_table(your_date_column) VALUES (DATE '2099-02-22');
Use a timestamp literal (which also allows you to specify the time):
INSERT INTO your_table(your_date_column) VALUES (TIMESTAMP '2099-02-22 00:00:00');
Explicitly convert the string using TO_CHAR and the correct format model:
INSERT INTO your_table(your_date_column)
VALUES (TO_DATE('22-FEB-99', 'DD-MON-YY', 'NLS_DATE_LANGUAGE=English'));
fiddle
Fixing invalid data
If you have the data as 1999 and want 2099 then you will need to fix it:
UPDATE your_table
SET your_date_column = your_date_column + INTERVAL '100' YEAR(3)
WHERE your_date_column = DATE '1999-02-22';
or:
UPDATE your_table
SET your_date_column = ADD_MONTHS(your_date_column, 1200)
WHERE your_date_column = DATE '1999-02-22';
or:
UPDATE your_table
SET your_date_column = DATE '2099-02-22'
WHERE your_date_column = DATE '1999-02-22';
2-digits year is evil (does Y2K ring a bell?). You should really use 4 digits for years. Meanwhile, see whether YY vs. RR format models do any difference in your case.
(you don't have to alter the session; my database uses different date format and language so I'm setting it now)
SQL> alter session set nls_date_format = 'dd.mm.yyyy';
Session altered.
SQL> alter session set nls_date_language = 'english';
Session altered.
Sample data and how yy/rr affect the result:
SQL> with test (col) as
2 (select '22-FEB-99' from dual)
3 select to_date(col, 'dd-mon-yy') val1,
4 to_date(col, 'dd-mon-rr') val2
5 from test;
VAL1 VAL2
---------- ----------
22.02.2099 22.02.1999
SQL>

How do I pull an extra row when pulling data from between dates?

I'd like to pull another row with the nearest date before the beginning of the following query from a sqlite db:
select * from inv WHERE TIME BETWEEN date1 AND date2
Is there a simple addition to the query or do I need to pull in more data and do the transformation at the end?
Thank you
Use UNION for the row with the maximum TIME that is less than date1:
select * from inv WHERE TIME BETWEEN date1 AND date2
UNION
select * from inv WHERE TIME = (select MAX(TIME) from inv WHERE TIME < date1)
If there would be more than 1 additional rows and you want exactly 1, you can add to the above code:
LIMIT 1

SQLite - Returning records in a specific month and year in date

I'm trying to get the records with a specific month and year like this:
SELECT * from table where strftime('%m', date) = '?'
if I test this query:
SELECT strftime('%m', date) from table
it return 19, but there's only records with may in month, so I thought the result was 5, but it's 19! Why?
What's wrong with my query? How can I return specific records using a specific value for month and year, linke 5 (may) and 2015
Milliseconds is not one of SQLite's supported date formats.
You have to convert these values into some supported format first (here: Unix timestamp):
SELECT * FROM MyTable WHERE strftime('%m', date / 1000, 'unixepoch') = ?

Selecting Rows with based on Count (SQLite)

Hoping for some help with this:
1) I am trying to select all calls (rows) for CustomerIDs that show up 6 or more times within a 30 day rolling period, so if the CustomerID is within the file 6 or more times within 30 days, then it would provide me with all records for that CustomerID.
2) I also need to select all calls for CustomerIDs that show up 2 or more times within a 30 day rolling period but ONLY if two certain columns also match (CallType1 and CallType2). Very similar to the query with the 6 calls but we need to consider that the call types are exactly the same too.
SELECT * FROM tablename
WHERE CustomerID IN (SELECT CustomerID FROM tablename
WHERE "CustomerID"
IN ('MyProgram'));
The query above selects all of the CustomerIDs which reach my program. I need to add the logic to count >=6 CustomerIDs (item 1 above) and then a second query to get the >=2 with the same CallTypes.
The innermost subquery computes how many calls there are in the window beginning at First.
The middle subquery checks this value for every possible window in the table. (This is inefficient, but SQLite has no window functions.)
SELECT *
FROM TableName
WHERE CustomerID IN (SELECT CustomerID
FROM TableName AS First
WHERE (SELECT COUNT(*)
FROM TableName
WHERE Date BETWEEN First.Date
AND date(First.Date, '+30 days')
AND CustomerID = First.CustomerID
) >= 6)
This assumes that there is a column Date using the default date format (yyyy-mm-dd).

SQLite3 /Python: Update Query to populate a field by taking the difference from two fields in the same table

My table: tblTest:
RunID,StartTime, EndTime, Period
1,2013-03-30 18:08:14-04,2013-04-01 10:57:22-04
2,2013-04-03 12:13:10-04,2013-04-03 18:05:34-04
3,2013-04-04 06:02:30-04,2013-04-05 10:42:00-04
4,2013-04-05 10:43:00-04,2013-04-06 13:23:06-04
I am attempting to update the table to calculate the column Period.
The query that I am using is:
UPDATE tblTest SET Period = (SELECT strftime('%s',substr(endtime,1,19)) -
strftime('%s',substr(starttime,1,19)) From tblTest)
but to my surprise it updates all Periods with the same value from the first line.
What am I doing wrong?
A subquery like (SELECT ... FROM tblTest) without a WHERE condition returns all records of the table.
In a context where only one value is expected (like in the SET expression), only the first such record is used.
You can just directly access the columns of the table that you are updating:
UPDATE tblTest
SET Period = strftime('%s', substr(EndTime, 1, 19)) -
strftime('%s', substr(StartTime, 1, 19))

Resources