I am using greendao or sqlite and my model (User) has a DOB column which stores the birthdate of the user. How can I find the users which have birthday between a range of dates?
I am using following query in mysql but cannot find a way to do this using sqlite:
SELECT *
FROM user
WHERE datediff( MAKEDATE( YEAR(NOW()) , DAYOFYEAR(dob) ) , NOW())
BETWEEN 0 AND 7
OR datediff( MAKEDATE( YEAR(NOW())+1 , DAYOFYEAR(dob) ) , NOW())
BETWEEN 0 AND 7
OR datediff( MAKEDATE( YEAR(NOW())-1, DAYOFYEAR(dob) ), NOW())
BETWEEN 0 AND 7;
Like SQLite documentation says, there is no Date format in SQLite (http://www.sqlite.org/datatype3.html).
So, greenDAO uses timestamp to save Dates. Maybe you are looking for this kind of query:
Date startRangeDate = new Date();
Date endRangeDate = new Date();
DeveloperDao targetDao = daoSession.getDeveloperDao();
QueryBuilder<Developer> qb = targetDao.queryBuilder();
qb.where(Properties.Birthday.between(startRangeDate.getTime(), endRangeDate.getTime()));
After lot of trying, I finally came up with this solution. I am posting this so it may help somebody in future:
public static List<Customer> getThisWeekCustomersByBirthday(Context context,int limit, int offset) {
String whereQuery = " julianday(strftime('%Y','now','localtime')||strftime('-%m-%d',datetime(dob/1000, 'unixepoch'),'localtime')) between julianday(strftime('%Y-%m-%d','now','weekday 0','-7 days','localtime')) and julianday(strftime('%Y-%m-%d','now','weekday 0','localtime')) "
+ "OR julianday(strftime('%Y','now','+1 year','localtime')||strftime('-%m-%d',datetime(dob/1000, 'unixepoch'),'localtime')) between julianday(strftime('%Y-%m-%d','now','weekday 0','-7 days','localtime')) and julianday(strftime('%Y-%m-%d','now','weekday 0','localtime')) "
+ "OR julianday(strftime('%Y','now','-1 year','localtime')||strftime('-%m-%d',datetime(dob/1000, 'unixepoch'),'localtime')) between julianday(strftime('%Y-%m-%d','now','weekday 0','-7 days','localtime')) and julianday(strftime('%Y-%m-%d','now','weekday 0','localtime')) ";
Query query = getCustomerDao(context).queryBuilder().where(
new WhereCondition.StringCondition(whereQuery)).limit(limit).offset(offset).build();
return query.list();
}
Related
I am trying to create a trigger like below in sqlite android. It works fine in other sqlite engine but shows syntax error in android. Please help me to make this update statement work.
create trigger if not exists trigger_cascade_update_carry_forward
after update on cf_details
begin
update cf_details set cf = c_f from (with recursive dates_after(d) as
( values(new.date) union
select strftime('%Y-%m',d||'-01','+1 month') as next_month
from dates_after where exists(select 1 from cf_details where date = next_month and account_id = new.account_id))
select d,c_f from dates_after,(select cf+net as c_f from cf_details where account_id = new.account_id and date = strftime('%Y-%m',(select d from dates_after order by d limit 1)||'-01','-1 month'))) where date = d;
end;
SELECT * FROM EVENT_total_time
WHERE USER_ID = 2
AND LEVEL_SEQUENCE_NUMBER = 1
AND DATETIME( TIMESTAMP ) BETWEEN DATETIME('now','-7 days') AND DATETIME('now')
ORDER BY datetime( TIMESTAMP ) ASC
and the DB has
PRINTING TABLE EVENT_total_time
0 {
_id=56
USER_ID=2
TIMESTAMP=2016-02-15 21:29:29
EPOCH_TIME=1455571769621
NEW_VALUE=3.034
LEVEL_ID=7
LEVEL_SEQUENCE_NUMBER=1
EXTRAS={"old_value":0}
}
1 {
_id=57
USER_ID=2
TIMESTAMP=2016-02-15 21:29:29
EPOCH_TIME=1455571769822
NEW_VALUE=3.219
LEVEL_ID=7
LEVEL_SEQUENCE_NUMBER=1
EXTRAS={"old_value":3.034}
}
this query was ran 30sec ago so ... datetime('now') should be 15.02.2016 21:32:00 ....
I ran this query and it produced an empty result. Can someone spot why?
In a database I have saved the date in form of 3 columns: Year, Month, Day_of_Month
( I know it might not be a best way to save the date but I make certain other queries for which this format felt suitable.)
Now I wish to get all the rows where the date is in between two specified dates. I went through previous stackoverflow questions, but most of them have saved the date as a single entity.
This is how I tried:
I have a MySqLiteHelper class with all the column names declared. I also create the table there. COLUMN_DATE_YEAR, COLUMN_DATE_MONTH and COLUMN_DATE_DAY are the string storing the column names.
int fyear, fmonth, fday; // I populate those initial date values
int tyear, tmonth, tday; // I populate those target date values
String selection = MySQLiteHelper.COLUMN_DATE_YEAR + " >= '"+fyear+"' AND "+ MySQLiteHelper.COLUMN_DATE_DAY + " >= '"+fday+"' AND "
+ MySQLiteHelper.COLUMN_DATE_MONTH + " >= '"+fmonth+"' AND " + MySQLiteHelper.COLUMN_DATE_YEAR + " <= '"+tyear+"' AND "
+ MySQLiteHelper.COLUMN_DATE_DAY + " <= '"+ tday+"' AND "+ MySQLiteHelper.COLUMN_DATE_MONTH + " <= '"+tmonth+"'";
String []column = {MySQLiteHelper.COLUMN_MOOD_LEVEL};
Cursor cursor = database.query(MySQLiteHelper.TABLE_NAMES, column, selection, null, null, null, null);
Now the problem with this approach is that it will give no results for the query between 25 Feb 2013 and 17 March 2013 as the date 25th > 17th, even though the month 2 < 3. This might require some kind of nested where clause. However I am unable to form a nested 'Where' using '.query' method.
Please suggest a way to query for the entries stored in between these two dates. Thanks in advance.
There's no reason why you shouldn't be able to run a somewhat more complex WHERE clause, as follows (for date >= 2013-02-17):
( YEAR > 2013 OR ( YEAR = 2013 AND ( MONTH > 2 OR ( MONTH = 2 AND DAY >= 17 ) ) ) )
This will work, but it's for from optimal. You'd be better off correcting your database design.
Correction: You must fix your database design. Either store the date as DATE type or as ISO string: yyyy-mm-dd.
Bonus: Say you have the following right now:
CREATE TABLE theTable(
....
THEYEAR TEXT,
THEMONTH TEXT,
THEDAY TEXT );
To convert the date to a usable format, you can simply run the following:
ALTER TABLE theTable
ADD COLUMN THEDATE TEXT;
UPDATE theTable
SET THEDATE = THEYEAR || substr( '0' || '-' || THEMONTH, -2, 2 ) || '-' || substr( '0' || THEDAY, -2, 2 );
Once you've done that, you can then query using the BETWEEN clause.
Using your current schema, try reordering your WHERE clause. You need to compare the largest columns first, i.e. year, month, day. With your current year, day, month you cannot accurately compare dates that cross over into new months.
For example: day >= 25 and day <= 17 creates an invalid range. It doesn't account for the correct range: >25, wrap to 1, then <17...
Without changing the table structure the below query will work for you, try it
select * from TableName WHERE (10000*ColumnYear+100*ColumnMonth+ColumnDay >= 20131009) and (10000*ColumnYear+100*ColumnMonth+ColumnDay <= 20131121);
I need that every time I make a change to a certain record from a table in SQLite, in the column lastChangedDate to set the time from France. Here is the structure of my table :
CREATE TABLE name(
id VARCHAR(36) PRIMARY KEY
, pos_report_id VARCHAR(36)
, path_name VARCHAR(64)
, photo_name VARCHAR(64)
, from_scratch INTEGER DEFAULT 0
, lastChangedDate DATETIME DEFAULT (DATETIME('now', 'utc', '1 hours'))
)
I see that DATETIME('now') returns 2 hours before my real time and DATETIME('now', 'utc', '1 hours') returns with 3 hours before my time. Why is happening this? I need the application to work in more countries, so I cannot use localtime.
Any idea how to solve this?
I have the same problem (using sqlite on Raspbarry Pi). 'utc' obviously only calcultes the difference according to location and timezone. I got it running like this:
select datetime(datetime('now', 'localtime'), 'utc');
Also check out the other variation of my VIEW [NOW] for sensor logging purpose.
CREATE VIEW [NOW] AS
SELECT datetime('now', 'localtime') as LOCAL,
datetime(datetime('now', 'localtime'),'utc') as UTC,
substr(datetime('now', 'localtime'),1,17)||'00' as TimeSlot_1min,
substr(datetime('now', 'localtime'),1,15)||'0:00' as TimeSlot_10min,
substr(datetime('now', 'localtime'),1,14)||'00:00' as TimeSlot_1h;
try datetime('now','localtime') instead of DATETIME('now', 'utc', '1 hours')
Ok dont use default time for lastChangedDate
CREATE TABLE name(
id VARCHAR(36) PRIMARY KEY
, pos_report_id VARCHAR(36)
, path_name VARCHAR(64)
, photo_name VARCHAR(64)
, from_scratch INTEGER DEFAULT 0
, lastChangedDate DATETIME)
)
then when you want to add record to table, you can calculate the time in France and add this value to your database
//Calendar cal = Calendar.getInstance();
//Log.v("hata",String.valueOf(cal.get(Calendar.HOUR)));
Calendar c = Calendar.getInstance();
// It is local time
Log.v("time",String.valueOf(c.getTime()));
TimeZone z = c.getTimeZone();
int offset = z.getRawOffset();
if(z.inDaylightTime(new Date())){
offset = offset + z.getDSTSavings();
}
// france is GMT2
int offsetHrs = offset / 1000 / 60 / 60;
int offsetMins = offset / 1000 / 60 % 60;
// Offsets
Log.v("time",String.valueOf(offsetHrs));
Log.v("time",String.valueOf(offsetMins));
c.add(Calendar.HOUR_OF_DAY, (-offsetHrs));
c.add(Calendar.MINUTE, (-offsetMins));
// FRANCE time
Log.v("time",String.valueOf(c.getTime()));
I have to search a database that is 26024 entries and counting. It used to be fast with less records but now is taking like 10 seconds and slowing the app. I was wondering if i could get advice as to how speed up the process or if i'm doing anything wrong. Here is the code.
while (cursor.moveToNext()) {
String word = cursor.getString(0);
if (word.equals(input)) {
String nikus = cursor.getString(1);
String def = cursor.getString(2);
ret.append(" " + nikus + "\n"+ def + "\n");
g = null;
}
EDIT:
In my Database i have a definitions table and in the table there are 3 fields one is the words to be compared to, the sencond is the full word, and the third is the definition itself. Hopefully that helps you guys a little more.
CREATE TABLE [definitions] (
[word] TEXT,
[fullword] TEXT,
[definition] TEXT);
EDIT: here is the error im getting
01-04 00:47:54.678: E/CursorWindow(4722): need to grow: mSize = 1048576, size = 17, freeSpace() = 13, numRows = 15340
laalto's comment above is correct. You should be running a select with a where clause that only pulls back the rows where word is equal to input (don't forget about case sensitivity.) An index on the word column will help the query go even faster.