I want to know how can i use MAX MIN command with ORMLITE.
For example lets say we have this table
Table Name = Example
Column 1 = id
Column 2 = name
In ORMLITE how can i get max id ? I looked here but i didnt't understand exactly..
Can someone show me example about Max min in ORMLITE ?
QueryBuilder<Account, Integer> qb = accountDao.queryBuilder();
qb.selectRaw("MIN(orderCount)", "MAX(orderCount)");
// the results will contain 2 string values for the min and max
results = accountDao.queryRaw(qb.prepareStatementString());
String[] values = results.getFirstResult();
I found this from documentation
This is how I query for max ID in my code:
QueryBuilder<Example, String> builder = dao.queryBuilder();
builder.orderBy("id", false); // true or false for ascending so change to true to get min id
Example example = dao.queryForFirst(builder.prepare());
String id = null;
if (example == null)
id = "-1";
else
id = example.getId();
A couple of alternative answers can also be found here:
ORMLite - return item w/ maximum ID (or value)
You can use:
dao.queryRawValue("select MAX(columnName) from tableName")
It will directly return long value.
refer: http://ormlite.com/javadoc/ormlite-core/doc-files/ormlite_5.html#DAO-Methods
queryRawValue(String query, String... arguments)
Perform a raw query that returns a single value (usually an aggregate function like MAX or COUNT). If the query does not return a single long value then it will throw a SQLException.
Related
I'm using Sugar ORM to query a list of apps. I have a boolean column for tagging fields in this using:
#Setter #Getter public boolean isNew = false;
Now after API call I will update and save the record to tag all new apps and then for display I will just query it using:
List<AppsModel> app_list = AppsModel.find(AppsModel.class, "is_new = ?", "true");
Problem is that it returns 0 entry where it to have 3 on my end. To check I get all the list and check the column one by one to check its values:
List<AppsModel> test = AppsModel.listAll(AppsModel.class);
for(int i=0;i<test.size();i++){
Log.e("Test app size", String.valueOf(test.get(i).isNew()));
}
And it returns 3 as expected with true values. I can make use of this loop for list but I don't want to as I want to keep my code clean as possible.
Am I missing something here?
Okay I found the answer here from satyan himself
So basically, using "true" will match it as String. So instead use:
List<AppsModel> app_list = AppsModel.find(AppsModel.class, "is_new = ?", "1");
As SQlite store boolean values as 0 and 1.
I would like to select a row from a table, but I only want to get one row and the row will be selected randomly.
I would like to select a row from a table, but I only want to get one row and the row will be selected randomly.
There isn't any special method calls which do this but there are ways that you can use the QueryBuilder to accomplish this.
If you have a numerical id, something like like should work:
qb = dao.queryBuilder();
qb.where().raw("id >= (ABS(RANDOM()) % MAX(id) + 1)");
entity = qb.queryForFirst();
Sqlite RANDOM() returns a large positive or negative integer. ABS() makes it just positive, MAX(id) allows us to then mod by the maximum id value. The +1 allows us to actually choose the max id row.
You can use queryRaw:
Relation result = null;
String query = "SELECT * from relations ORDER BY RANDOM() LIMIT 1";
try {
result = queryRaw(query, getRawRowMapper()).getFirstResult();
} catch (SQLException e) {
e.printStackTrace();
}
What I actually did was to get the List<> of the selected items from the database and then use a Random object, using the size() of the return list as the maxInt. And yes I did check for nulls.
Dao dao = getHelper().getObjectDao();
PreparedQuery<Object> query = dao.queryBuilder().[query].prepare();
Object object = null;
List<Object> resultList = dao.query(query);
if(resultList != null && resultList.size() > 0){
Random random = new Random();
int selected = random.nextInt(resultList.size() - 1);
object = resultList.get(selected);
}
It works for me:
dao.queryBuilder().orderByRaw("RANDOM()").queryForFirst();
How can I get Dynamo's UpdateItemRequest to either ignore the range key, or do a coarse test such as not null?
I am using a range key which contains the time of a record update. Separately, I update rows which I select using an ID field which is not a key. I update the ID field using an expectedAttribute in an UpdateItemRequest. Dynamo's UpdateItemRequest forces me to specify a range key value. My ID update code will not know the range key value. Can I somehow not specify a range key and not get an error? Or can I provide a simple range key test like not null?
When I remove the range key, AWS throws an error, "The provided key element does not match the schema"
// construct the update map
HashMap<String, AttributeValueUpdate> updates = new HashMap<String, AttributeValueUpdate>();
AttributeValue av = new AttributeValue().withN("1");
AttributeValueUpdate avu = new AttributeValueUpdate().withValue(av).withAction(AttributeAction.PUT);
updates.put("Column1", avu);
AttributeValue av2 = new AttributeValue().withN("2");
AttributeValueUpdate avu2 = new AttributeValueUpdate().withValue(av2).withAction(
AttributeAction.PUT);
updates.put("Column2", avu2);
// construct the key map
HashMap<String, AttributeValue> keyMap = new HashMap<String, AttributeValue>();
AttributeValue hashValue = new AttributeValue().withN("10");
keyMap.put("hashKey", hashValue);
AttributeValue lastModKeyValue = new AttributeValue().withN("1404175127074");
// ****** I want to remove this key but Dynamo throws an error
keyMap.put("problemRangeKey", lastModKeyValue);
// expected value comparison
AttributeValue idValue = new AttributeValue().withN("100");
ExpectedAttributeValue expected = new ExpectedAttributeValue(idValue);
UpdateItemRequest request = new UpdateItemRequest().withTableName(DatabaseConstants.CHART_TABLE)
.withKey(keyMap).withAttributeUpdates(updates).addExpectedEntry(ID, expected);
ddb.updateItem(request);
For clarity, here is how I use the range key to find rows after a specific time. If I remove this time range, then I would do a big scan every time to find rows after a specific time.
Map keyConditions = new HashMap();
AttributeValue attribute = new AttributeValue().withN("10");
Condition hashKeyCondition = new Condition().withComparisonOperator(ComparisonOperator.EQ.toString())
.withAttributeValueList(attribute);
keyConditions.put("hashKey", hashKeyCondition);
// specify new records
long lastQueryTime = PrefsActivity.getLastDynamoQueryTime(activity);
String lastTimeString = String.valueOf(lastQueryTime);
Log.v(TAG, "get Charts from dynamo that are after " + lastTimeString);
// update the query time to now
long now = System.currentTimeMillis();
PrefsActivity.setLastDynamoQueryTime(activity, now);
AttributeValue timeAttribute = new AttributeValue().withN(lastTimeString);
Condition timeCondition = new Condition().withComparisonOperator(ComparisonOperator.GT.toString())
.withAttributeValueList(timeAttribute);
keyConditions.put("problemRangeKey", timeCondition);
List<Map<String, AttributeValue>> ChartsInMaps = new ArrayList<Map<String, AttributeValue>>();
Map lastEvaluatedKey = null;
QueryRequest request = new QueryRequest().withTableName("tableName")
.withKeyConditions(keyConditions).withExclusiveStartKey(lastEvaluatedKey);
QueryResult result = ddb.query(request);
I'm working with the latest AWS Android SDK. In the sample above, I'm setting the hashKey to "10". In practice, that will vary.
Thanks in advance for any help!
Jeff
The question is, you want to update all items with a specific hashKey value and a specific column value (column name is id).
The table is Hash-Range schema. Since you don't know the range key, you have to fetch all the rows with that hashKey and then do a filter based on the column value (ID == value). You can use query filter to do that efficiently. Then for each row in your query, do a conditional put with expected value (ID == value) just to be sure.
QueryRequest request = new QueryRequest();
// set up query request (table name, etc)
// set up query filter (ID == value)
QueryResponse response = client.query(request)
for (item in response.items):
PutItemRequest req = new PutItemRequest();
// set up put item request
// set up primary key for item to update
// hashkey = item.hashkey
// rangekey = item.rangeKey
// set up expected value (ID == value)
client.updateItem(req)
On the other hand, since you want to efficiently query all the rows after a specific time, you can create a Local Secondary Index with "time" as a range key instead of making "time" the range key of your base table. You can still do efficient query using LSI (compared with scanning the table and filter by time). Whats more important is, if your "ID" attribute can uniquely identify a row with your hashkey, you can make "ID" the range key of your base table. This way you can also update the item efficiently since you already know the hashkey value and range key value (id value).
Of course it only truly benefits you when your hashkey and "ID" can uniquely identify a row :)
Hi I need to use order by max(columnName) in ORMLite. I have the SQL query but I need to know how this query is used. This is my query:
SELECT * FROM table where place = 'somePlace' group by name
order by MAX (statusDate)
statusDate column contains date in "yyyy-dd-mm" format. The result I got is the list with recentDates.
Use a query builder, and function where and orderBy to preoceed
QueryBuilder<YourObject, Integer> q = yourDaoObject.queryBuilder();
Where<YourObject, Integer> wh = q.where();
wh.eq("place", "some_place");
q.orderBy("statusDate", false);
List<YourListOfObects> yourList = q.query();
But before that you should store a long instead to store your Date https://stackoverflow.com/a/6993420/2122876
i got same names with different dates and i need only the recent date.
If you are trying to get element from Table with the maximum statusDate then you should be doing an descending order-by with a limit of 1. Something like:
QueryBuilder<Foo, Integer> qb = fooDao.queryBuilder();
qb.where().eq("place", "some_place");
qb.orderBy("sttusDate", false); // descending sort
// get the top one result
qb.limit(1);
Foo result = qb.queryForFirst();
I did something like this. Please create your own query builder on the first line.
QueryBuilder<MyRowObject, Integer> queryBuiler = "Get Query builder" //getDaoXXX().queryBuilder();
MyRowObject firstLatestRow = queryBuiler.orderBy("dateColoumn", false).queryForFirst();
Hope this helps
How to update table sqlite_sequence in Ormlite ? I just need update seq. How can I get that table via ORMLite ?
EDIT
I can't find ORLite tool to do this, so instead I use simple sqlite query. In my class extends OrmLiteSqliteOpenHelper I use SQLiteDatabase to make that update.
EDIT2 ;)
In my project I persist class Lesson and class WeekDefinition.
class Lesson{
#DatabaseField(generatedId=true)
private int id;
...
}
class WeekDefinitions{
#DatabaseField(generatedId=true)
private int id;
#DatabaseField(foreign=true, columnName="lesson_id")
private Lesson lesson;
...
}
Now , when I add new lessons, id is increment. For example
id = 1 Math
id = 2 English
id = 3 Medicine
and in weekDefinition :
id = 1 lesson_id = 1 nr = 20
id = 2 lesson_id = 1 nr = 22
id = 3 lesson_id = 2 nr = 32
...
id = 12 lesson_id = 3 nr = 3
SQLite add this row into sqlite_sequence ( when use autoincrement )
rowId = 1 name = lesson seq = 3
rowId = 2 name = weekDefinition seq = 12
Now, I delete all rows from tables Lesson and WeekDefinition. Lesson and WeekDef are empty after that, but sqlite_sequence is still the same. And this is problem because id in table lesson start from value 4 ( seq from sqlite_sequence for lesson and add 1 ) :
id = 4 Math
id = 5 English
id = 6 Medicine
and weekDefinition
id = 13 lesson_id = 1 nr = 20
id = 14 lesson_id = 1 nr = 22
id = 15 lesson_id = 2 nr = 32
and for lesson id = 4 , Math i should get weekDefinitios, but in weekDefinitions lessons_id has value only from 1 to 3
And this is my problem. I need "reset" sqlite_sequence table ( or there is better solution ?)
Building on Marcos Vasconcelos' answer:
UPDATE sqlite_sequence SET seq = (SELECT MAX(col) FROM Tbl) WHERE name="Tbl"
This query will set seq to the largest value in the col identity column in the Tbl table, so there is no risk of violating constraints.
Inside your .db file there's an table called sqlite_sequence
Each row has two columns
name which is the name of the table
seq a integer indicating the current last value at this table
You can update it to 0
But beware if your table use this id as the unique identifier.
UPDATE SQLITE_SEQUENCE SET SEQ= 'value' WHERE NAME='table_name';
If you want to issue general database commands in ORMLite, you can use the updateRaw method. See the javadocs. There is also executeRaw for other commands.
lessonDao.updateRaw("delete from 'lesson';");
lessonDao.updateRaw("delete from sqlite_sequence where name='lesson';");
weekDefinitionDao.updateRaw("delete from 'weekdefinition';");
weekDefinitionDao.updateRaw(
"delete from sqlite_sequence where name='weekdefinition';");
You could also drop and recreate the table as well:
TableUtils.dropTable(WeekDefinition.class);
TableUtils.dropTable(Lesson.class);
TableUtils.createTable(Lesson.class);
TableUtils.createTable(WeekDefinition.class);
I think the real question is why is your application depending on this database internal number? It really shouldn't care.
How about not displaying the number at all so it can be 1 or 1001 and your application won't matter?
You could also never remove the lessons at all but maybe add a hidden boolean field. So if they get re-added, the hidden field could be set to false and Math would still be at id #1.
This worked for me in my database : (I Set the id before one, then after deleting one row, when I add new data row again, the auto increment serial remain ok ) :
public void updateSerialNumber ( long memberId){
String query = "UPDATE SQLITE_SEQUENCE SET SEQ= '"+(memberId-1)+"' WHERE NAME='"+ReportBigHelper.TABLE_MEMBER+"'";
database.execSQL(query);
}