Sqlite group dates by day - java

I'm trying to retrieve a list of different days from table. They are stored in integer.
cal.getTime().getTime()
Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT represented by this Date object.
What I've written
select strftime('%d-%m-%Y'," + date_clmn + ") from "
+ TABLE_NAME +" group by strftime('%d-%m-%Y'," + date_clmn + ")"
Next, I convert these values toString.
What I get:
24-11--471
And after that when I try to make query with
strftime('%d-%m-%Y',date_clmn)=24-11--471
I get nothing.
What's wrong?
Will I run in trouble with timezone using this way?
If there are some other ways make it, I'll be glad to hear you.
Thanks in advance.
UPDATE
Tried "date(" + date_clmn+ ",'unixepoch')"
now retrieved value is "1970-01-01"

Since you are not storing a date in your table, you need to change your field. Try with this code:
"select strftime('%d-%m-%Y'," + date_clmn + "/1000,'unixepoch') from "
+ TABLE_NAME +" group by strftime('%d-%m-%Y'," + date_clmn + "/1000,'unixepoch')"

I'm adding this because I think it could be helpful to someone. As per documentation strftime() returns a string date in a given format. So in this clause:
strftime('%d-%m-%Y',date_clmn) = 24-11--471
^ ^
string this expression returns an integer
There's a type mismatch here that SQLite doesn't detect. Even query will run perfectly (I tested it and runs without errors), but of course it won't retrieve any row.
The right comparisson would be:
strftime('%d-%m-%Y',date_clmn) = '24-11--471'
Testing: Here's a little piece of code to test this behavior:
CREATE TABLE dateTest(myDate VARCHAR);
INSERT INTO dateTest(myDate) VALUES ('2013-08-29 18:57:00');
SELECT strftime('%Y-%m-%d',myDate) AS formatted, myDate FROM dateTest WHERE strftime('%Y-%m-%d') = 2013-08-29; /* this won't retrieve any row */
SELECT strftime('%Y-%m-%d',myDate) AS formatted, myDate FROM dateTest WHERE strftime('%Y-%m-%d') = '2013-08-29'; /* this will retrieve '2013-08-29 | '2013-08-29 18:57:00' */
And here's the output:

Related

Add number of days in Oracle DB using SQL in java code

I am using below SQL in java code to update date in Oracle DB.
UPDATE CUS_LOGS SET START_DATE=to_date(systimestamp + 3,'DD-MON-RRRR'), END_DATE=to_date(systimestamp + 21921,'DD-MON-RRRR')
WHERE CUS_ID IN ('9b90cb8175ba0ca60175ba12d8711006');
My expectation is:
START_DATE = 05-NOV-2022
END_DATE = 08-NOV-2082.
However the result I see as
START_DATE = 05-NOV-2022
END_DATE = 08-NOV-1982 **********
Apparently issue happens when the date pass 31-12-2049. i.e. adding + 9922 as of today (02/11/2022)
The problem is that you're relying on implicit conversion, which is using your NLS settings, which are formatting dates as string with 2-digit years.
If your NLS_DATE_FORMAT is DD-MON-RR or DD-MON-YY then doing
to_date(systimestamp + 3,'DD-MON-RRRR')
is really doing something like:
to_date(to_char(cast(systimestamp as date) + 3,'DD-MON-RR','DD-MON-RRRR')
which means it tries to convert the string '08-NOV-82' to a date using the mask 'DD-MON-RRRR'. The RRRR means that a 2-digit year like 82 is interpreted as 1982 - which is what you're seeing. Using DD-MON-YYYY would be even worse, as that would interpret 82 as 0082.
alter session set nls_date_format = 'DD-MON-RR'
select
to_date(sysdate + 3,'DD-MON-RRRR') as a,
to_char(to_date(sysdate + 3,'DD-MON-RRRR'), 'YYYY-MM-DD') as b,
to_date(sysdate + 21921,'DD-MON-RRRR') c,
to_char(to_date(sysdate + 21921,'DD-MON-RRRR'), 'YYYY-MM-DD') as d,
to_date(sysdate + 3,'DD-MON-YYYY') as e,
to_char(to_date(sysdate + 3,'DD-MON-YYYY'), 'YYYY-MM-DD') as f,
to_date(sysdate + 21921,'DD-MON-YYYY') as g,
to_char(to_date(sysdate + 21921,'DD-MON-YYYY'), 'YYYY-MM-DD') as h
from dual
A
B
C
D
E
F
G
H
05-NOV-22
2022-11-05
08-NOV-82
1982-11-08
05-NOV-22
0022-11-05
08-NOV-82
0082-11-08
So you would need to explicitly convert the date to a string with a 4-digit year, then convert it back again...
But you don't need to do any of that conversion. Just adding the number of days to the timestamp - which implicitly converts that to a date, but safely - gets the result you want:
alter session set nls_date_format = 'YYYY-MM-DD'
alter session set nls_timestamp_tz_format = 'YYYY-MM-DD HH24:MI:SS TZR'
select systimestamp,
systimestamp + 3,
systimestamp + 21921
from dual
SYSTIMESTAMP
SYSTIMESTAMP+3
SYSTIMESTAMP+21921
2022-11-02 10:42:24 +00:00
2022-11-05
2082-11-08
There's no point using systimestamp here though, you can avoid even that implicit conversion by using sysdate:
select sysdate,
sysdate + 3,
sysdate + 21921
from dual
SYSDATE
SYSDATE+3
SYSDATE+21921
2022-11-02
2022-11-05
2082-11-08
fiddle
You seem to be doing the conversion in order to remove the time portion of the current date/time - or, more correctly, set it to midnight as a date always has a time. But you can do that with trunc().
So, in summary, your update statement should just be:
UPDATE CUS_LOGS SET START_DATE=trunc(sysdate) + 3, END_DATE=trunc(sysdate) + 21921
WHERE CUS_ID IN ('9b90cb8175ba0ca60175ba12d8711006');
Your end date is roughly 60 years ahead; you might want to use add_months(trunc(sysdate), 60*12) and then add any additional days to that - maybe just keeping the + 3, inside or outside the add_months(), or both; add_months(trunc(sysdate) + 3, 60*12) + 3 would give the same result as + 21921, today anyway. But it isn't clear exactly what you're doing...
And you can add intervals rather than a number of days, which is a bit more explicit; but that works less well for adding months/years because it can lead to invalid-date errors, e.g. if you try to add a year interval to Feb 29th.
You can simplify the query and prevent issues from implicit timestamp-to-date-to-string conversions (as described by #Alex Poole) using:
UPDATE CUS_LOGS
SET START_DATE = TRUNC(SYSDATE) + INTERVAL '3' DAY,
END_DATE = ADD_MONTHS(TRUNC(SYSDATE), 60*12) + INTERVAL '6' DAY
WHERE CUS_ID = '9b90cb8175ba0ca60175ba12d8711006';

Hibernate - compare DateTime field with Restrictions.like

I have a createDateTime field with Date dataType in my entity class and hibernate generated a column with datetime type in the mysql table. Now, I need to compare createDateTime field with values without seconds. In fact, one user can enter for example 2015-01-01 12:10 in the search field and I want to show the record that has 2015-01-01 12:10:10 crateDateTime as a result. I know this is possible with flat query:
SELECT * FROM table_test WHERE crateDateTime LIKE "2015-01-01 12:10 %"
But I don't know how I can do this via hibernate.
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm");
data = formatter.parse("2015-01-01 12:10");
//This returned null.
Criterion crtmp = Restrictions.like("createDateTime", data);
//This returned ClassCastException. Because second argument must have "Date" dataType not "String"
Criterion crtmp = Restrictions.like("createDateTime", data + "%");
You should create a Date variable e.g. createDateTimePlusOneMinute, than find a time range between your createDateTime and createDateTimePlusOneMinute, using the following restrictions
criteria.add(Restrictions.ge("createDateTime", createDateTime));
criteria.add(Restrictions.lt("createDateTime", createDateTimePlusOneMinute));
// datetime comparison
Select c from Customer c where c.date<{d '2000-01-01'}

How can i search for the year in a date via a query?

The records in the db look like this:
10//12/2013
10/13/2013
10/16/2013
10/20/2013
I want to search 2013 in the above records. Do i have to split first above values?
from CustomerRelations where DATE like'" + input + "'
Can I use like here?
Or how else can I do this?
Query q = session.createQuery("from CustomerPayment where DATE like '" + code + "'");
The Above code does not work.
Since you've saved the dates as VARCHAR do a wildcard String match
Query q = session.createQuery("from CustomerPayment where DATE like '%" + code + "'");
LIKE clause lets you use two wilcards:
_ = matches just one single character
% = matches any number of characters
Ideally, you should have created your table with a TIMESTAMP column. That would allow you to compare dates accurately and build queries like "fetch all customer payments in the last three months" etc.
you can use
datepart(year,datefield)
where datefield is your field from which you want to retrieve the year
Query q = session.createQuery("SELECT date FROM CustomerPayment WHERE datepart(year,"+Convert.ToDateTime(datefield)+")="+ input+";
Try changing your query to
Query q = session.createQuery("SELECT date FROM CustomerPayment WHERE date LIKE '%"+input+"'"
since your date field is a string, you must do the lookup via a string compare

Is it possible to call DATE_ADD() in Java and store the value in a temporary date variable?

I have a doubt about adding days to Date in MySQL database.
The following is my code:
res=stat.executeQuery("select st_date from tmp1 where st_date = '"+t1.getText()+"'");
while(res.next())
{
System.out.println(res.getDate(1));
int i=0;
while(i<14)
{
statement.executeUpdate("Insert into datetab values(DATE_ADD('"
+res.getDate("st_date")+"',INTERVAL 1 DAY),'"+tempname+"')");
i=i+1;
}
}
All the updates in datetab table occur, but there is a problem. I will explain the problem with an example. If the date from tmp1 table is 28-12-2000, then after executing the insert query with date_add(), what happens is that 13 new inserts are happening, but all those inserts are "29-12-2000".
If the date from tmp1 table is 28-12-2000 Then after executing the insert query with date_add(), what happens is that 13 new inserts are happening, but all those inserts are "29-12-2000".
Because that is exactly what you are asking for. Your insert statement is:
"Insert into datetab values(DATE_ADD('" + res.getDate("st_date") +
"',INTERVAL 1 DAY),'" + tempname + "')"
Since read.getDate is not changing in the loop, the same value is inserted in every interation.
Instead of "Interval 1 DAY", use "Interval " + i + " Day" should insert different days. Is that what you are looking for?

Optimizing MySQL update query

This is currently my MySQL UPDATE query, which is called from program written in Java:
String query = "UPDATE maxday SET DatePressureREL = (SELECT " +
"Date FROM ws3600 WHERE PressureREL = (SELECT MAX" +
"(PressureREL) FROM ws3600 WHERE Date >= '" + Date +
"') AND Date >= '" + Date + "' ORDER BY Date DESC LIMIT 1), " +
"PressureREL = (SELECT PressureREL FROM ws3600 WHERE " +
"PressureREL = (SELECT MAX(PressureREL) FROM ws3600 " +
"WHERE Date >= '" + Date + "') AND Date >= '" + Date +
"' ORDER BY Date DESC LIMIT 1), ...";
try {
s.execute(query);
}
catch (SQLException e) {
System.out.println("SQL error");
}
catch(Exception e) {
e.printStackTrace();
}
Let me explain first, what does it do. I have two tables, first is ws3600, which holds columns (Date, PressureREL, TemperatureOUT, Dewpoint, ...). Then I have second table, called maxday, which holds columns like DatePressureREL, PressureREL, DateTemperatureOUT, TemperatureOUT,... Now as you can see from an example, I update each column, the question is, is there a faster way? I am asking this, because I am calling MAX twice, first to find the Date for that value and secondly to find the actual value. Now I know that I could write like that:
SELECT Date, PressureREL FROM ws3600 WHERE PressureREL =
(SELECT MAX(PressureREL) FROM ws3600 WHERE Date >= '" +
Date + "') AND Date >= '" + Date + "'
ORDER BY Date DESC LIMIT 1
That way I get the Date of the max and the max value at the same time and then update with those values the data in maxday table. But the problem of this solution is, that I have to execute many queries, which as I understand takes alot more time compared to executing one long mysql query because of overhead in sending each query to the server.
If there is no better way, which solution beetwen this two should I choose. The first, which only takes one query but is very unoptimized or the second which is beter in terms of optimization, but needs alot more queries which probably means that the preformance gain is lost because of overhead in sending each query to the server?
Doing 2 queries isn't really a problem for me, but they should be in a transaction (the reads and the write), this way you'll be sure that your update values are not wrong. With one query you do not have this problem.
I think the time lost in reading some data is nothing regarding the time lost by performing a write operation. A write operation is not by definition a fast thing, you could have triggers, you're maybe emptying the query cache from all requests impacting this table, the database needs to sync your write on disk, etc.
The more important thing for you is to keep your process simple, readable, and logic.
1) I think the problem goes deeper than just SQL optimization. Do you think this could be modeled differently where you don't have to migrate data like this (this much, and this often too btw) in the first place? Perhaps just using a FK/cross table to link the two together instead of migrating every field?
2) One query is much better than using JDBC to constantly go back and forth over the connection with new statements. That is a very expensive operation (each time). You will always want to stick to condensing queries into one as opposed to using iteration to make execute many statements.
Working from the inside out, it looks like all your subqueries do the same thing.
What's the point of having a where clause that does Date >= '" + Date + "') AND Date >= '" + Date + "' ?
Without going into column names or technical details, what are the purposes of your two tables?
String query = #"UPDATE maxday SET DatePressureREL = (SELECT Date FROM ws3600 WHERE PressureREL = (SELECT MAX(PressureREL) FROM ws3600 WHERE Date >= #Date) AND Date >= #Date ORDER BY Date DESC LIMIT 1), PressureREL = (SELECT PressureREL FROM ws3600 WHERE PressureREL = (SELECT MAX(PressureREL) FROM ws3600 WHERE Date >= #Date) AND Date >= #Date ORDER BY Date DESC LIMIT 1), ...";
After this, ideally if you were using a SelectCommand of some type instead of a string, you would
query.Parameters.Add(new MySqlParameter("#Date", yourdate));
Alternatively, you can just do this, although it opens you up to sql injection
query = query.replace("#Date", "'" + Date "'");
Either way, it makes the query considerably more legible.
If you can get all the values in one select query, this might work. Use a stored procedure accepting one parameter (date) that does:
One select statement, storing the values in a cursor, and
One update statement, using the values in the cursor.
Cursor Example

Categories