Android: Get highest value in column - sql

I have an URL pointing to content and I need to get the highest value contained in one of the columns. Is there any aggregate function that will accomplish that or do I have to do this manually?

If you're querying an Android content provider, you should be able to achieve this by passing MAX(COLUMN_NAME) in to the selection parameter of ContentResolver.query:
getContentResolver().query(uri, projection, "MAX(COLUMN_NAME)", null, sortOrder);
Where Uri is the address of the content provider. This should return the single row with the highest value in COLUMN_NAME.

Android's database uses SQLite, so SELECT MAX(thecolumn) FROM TheTable should work, just like in any other SQLite implementation (or for that matter any other SQL, "ite" or not;-). (If you're not using android.database you'd better specify what you're using instead;-).

That worked for me.
Based on the responses of #Reto Meier and #Florian von Stosch.
public static long getMaxId(Context context) {
long maxId = 0;
Cursor maxCursor = context.getContentResolver().query(
ProviderContentContract.CONTENT_URI,
new String[]{"MAX(" + Table._ID + ")"},
null,
null,
null);
if (maxCursor != null && maxCursor.moveToFirst()) {
maxId = maxCursor.getInt(0);
maxCursor.close();
}
return maxId;
}

Related

How do you make a reusable UDF that operates on a single column?

Instead of writing a query like
select * from xyz where mydomain IN ('foobar.com', 'www.example.com')
I want to write a function like
select * from xyz where one_of_my_domains(select mydomain as from_site)
But I want to be able to reuse this functions for any url in one of many tables. Currently when I use a function like this, I have to predefined what is returned and use it on the whole FROM part of the SQL statement. Is there any way to generalize a UDF to where I can use it on just 1 column instead of it operating over all rows. Here is my code right now that works but I have to predefine every output column which makes it not reusable.
domains = ['foobar.com', 'www.example.com'];
// The UDF
function has_domain(row, emit) {
var has_domain = false;
if (row.to_site !== null && row.to_site !== undefined) {
for (var i = 0; i < domains.length; i++){
if (domains[i] === String.prototype.toLowerCase.call(row.to_site)){
has_domain = true;
break;
}
}
}
return emit({has_domain: has_domain, trackingEventId: row.trackingEventId, date: row.date, from_site: row.from_site, to_site: row.to_site});
}
// UDF registration
bigquery.defineFunction(
'has_domain', // Name used to call the function from SQL
['from_site'], // Input column names
// JSON representation of the output schema
[{name: 'has_domain', type: 'boolean'}],
has_domain // The function reference
);
It might look a little messy - but below does exactly what you asked!
Make sure you are in Standard SQL (see Enabling Standard SQL)
CREATE TEMPORARY FUNCTION one_of_my_domains(x STRING, a ARRAY<STRING>)
RETURNS BOOLEAN AS
(x IN (SELECT * FROM UNNEST(a)));
WITH xyz AS (
SELECT 1 AS id, 'foobar.com' AS mydomain UNION ALL
SELECT 2 AS id, 'www.google.com' AS mydomain
),
site AS (
SELECT 'foobar.com' AS domain UNION ALL
SELECT 'www.example.com' AS domain
)
SELECT *
FROM xyz
WHERE one_of_my_domains(mydomain, ARRAY((SELECT domain FROM site)))
You're looking for scalar UDFs using standard SQL. They're much less awkward to use compared to those of legacy SQL.

Berkeley DB equivalent of SELECT COUNT(*) All, SELECT COUNT(*) WHERE LIKE "%...%"

I'm looking for Berkeley DB equivalent of
SELECT COUNT All, SELECT COUNT WHERE LIKE "%...%"
I have got 100 records with keys: 1, 2, 3, ... 100.
I have got the following code:
//Key = 1
i=1;
strcpy_s(buf, to_string(i).size()+1, to_string(i).c_str());
key.data = buf;
key.size = to_string(i).size()+1;
key.flags = 0;
data.data = rbuf;
data.size = sizeof(rbuf)+1;
data.flags = 0;
//Cursor
if ((ret = dbp->cursor(dbp, NULL, &dbcp, 0)) != 0) {
dbp->err(dbp, ret, "DB->cursor");
goto err1;
}
//Get
dbcp->get(dbcp, &key, &data_read, DB_SET_RANGE);
db_recno_t cnt;
dbcp->count(dbcp, &cnt, 0);
cout <<"count: "<<cnt<<endl;
Count cnt is always 1 but I expect it calculates all the partial key matches for Key=1: 1, 10, 11, 21, ... 91.
What is wrong in my code/understanding of DB_SET_RANGE ?
Is it possible to get SELECT COUNT WHERE LIKE "%...%" in BDB ?
Also is it possible to get SELECT COUNT All records from the file ?
Thanks
You're expecting Berkeley DB to be way more high-level than it actually is. It doesn't contain anything like what you're asking for. If you want the equivalent of WHERE field LIKE '%1%' you have to make a cursor, read through all the values in the DB, and do the string comparison yourself to pick out the ones that match. That's what an SQL engine actually does to implement your query, and if you're using libdb instead of an SQL engine, it's up to you. If you want it done faster, you can use a secondary index (much like you can create additional indexes for a table in SQL), but you have to provide some code that links the secondary index to the main DB.
DB_SET_RANGE is useful to optimize a very specific case: you're looking for items whose key starts with a specific substring. You can DB_SET_RANGE to find the first matching key, then DB_NEXT your way through the matches, and stop when you get a key that doesn't match. This works only on DB_BTREE databases because it depends on the keys being returned in lexical order.
The count method tells you how many exact duplicate keys there are for the item at the current cursor position.
You can use method DB->stat().
For example, number of unique keys in the BT_TREE.
bool row_amount(DB *db, size_t &amount) {
amount = 0;
if (db==NULL) return false;
DB_BTREE_STAT *sp;
int ret = db->stat(db, NULL, &sp, 0);
if(ret!=0) return false;
amount = (size_t)sp->bt_nkeys;
return true;
}

Selecting specific columns using linq: What gets transferred?

I refer to this example: Return selected specified columns
Quote:
If BlobDetails isn't the LINQ entity, then you can do it directly:
var qry = from b in dc.Blobs
orderby b.RowVersion descending
select new BlobDetails {
Id = b.Id, Size = b.Size,
Signature = b.Signature, RowVersion = b.RowVersion};
return qry.ToList();
I see that they are selecting specific column in a query through the ORM-tool LINQ TO SQL.
Critics of ORM-tools say that, if I remember correctly, that ORM-tools select and return entire objects from the table, and limits the options of selecting only specific columns as one can do through classic SQL-programming. Of course, I have my doubts about that when I see this example, but nevertheless, I still keep asking myself the question: Does the database return only the selected columns, or does it return the entire objects, leaving the column-filtering to the ORM-tool?
From this example, they also have a class called Blobdetails:
public class BlobDetails
{
public int Id { get; set; }
public string Signature { get; set; }
public int Size { get; set; }
public System.Data.Linq.Binary RowVersion { get; set; }
}
Do I need to create my own classes everytime I only wish to select a few columns from a table through LINQ?
You don't need to create new classes to select few columns from a table. You can use anonymous types for that.
var qry = from b in dc.Blobs
orderby b.RowVersion descending
select new { b.Id, b.Size, b.Signature, b.RowVersion};
return qry.ToList();
Only selected columns are transferred. There is no difference between using plain SQL and using LINQ to SQL. When you are executing LINQ query, it is converted to plain SQL and executed. Then result is mapped to your objects.
You can use SQL Server Profiler to see what query was generated and executed on server. Also you can use LINQPad to see what SQL will be generated from your query. In your case query will be same either you use BlobDetails or anonymous object:
SELECT [t0].[Id], [t0].[Size], [t0].[Signature], [t0].[RowVersion]
FROM [Blobs] AS [t0]
ORDER BY [t0].[RowVersion] DESC
when you do projections LINQ does indeed only select those columns and there is nothing preventing you from materializing it however you want. So in your example code
select new BlobDetails
{
Id = b.Id,
Size = b.Size,
Signature = b.Signature,
RowVersion = b.RowVersion
};
Only b.id, b.size, b.signature, & b.rowversion are selected. You can verify this with sql profiler or your debugger, I seem to recall there is also a function you can call on the datacontext to get the last query that was ran.
I think that the answer to your first question is already in the POST you mentioned. However...
If your BlobDetails is not LINQ entity you can simply use it in your select statement to define (shrink) your projection attributes. For example:
var qry = from b in dc.Blobs
select new BlobDetails { Id = b.Id, Size = b.Size }
would compile to SQL query like SELECT Id, Size FROM Blob ....
But if BlobDetails is LINQ entity you will need to use that AsEnumerable() hack otherwise you will get NotSupportedException: Explicit construction of entity type in query is not allowed.
var qry = from b in dc.Blobs.AsEnumerable()
select new BlobDetails { Id = b.Id, Size = b.Size }
Edit
As #Chris Pitman stated in his comment this AsEnumerable() approach could create serious bottleneck, beacause the whole table would be loaded in memory before applying the projection. So it is not recommended!
To your second question:
You will need to create custom class for objects that you want use easily outside the scope of the method. Properties of an anonymous object are visible only in the scope, where they have been declared and anonymous objects can be cast only to type object.
So if you want to return anonymous objects from method the return type would has to be an enumerable of object or dynamic as #xeondev stated in his comment.
There's no need to create your own classes, you can return an anonymous type. You can write something like this
var qry = from b in dc.Blobs
orderby b.RowVersion descending
select new {
Id = b.Id, Size = b.Size,
Signature = b.Signature, RowVersion = b.RowVersion};
return qry.ToList();
Although the signature of the method should look to something like this
public IEnumerable<object> GetItems()
or
public dynamic GetItems()
So if you are going to use the result of linq query in outer scope like you example suggest, it is highly recommended you create your own classes.

Linq to sql - get value from db function and not directly from the db field (while mapping properties)

When you map a table to an object, every property created corresponds to one db column.
I want to execute a db function on a column before it gets mapped to the property, so the property gets the value returned by the db function, and not the column
I was trying to achieve that by Expression property of ColumnAttribute (as in the example below), so instead of BirthDate the usrFn_UTCToLocalTime(BirthDate) is returned
but it does not seem to be working and still gets pure value of the column.
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage = "_BirthDate", DbType = "DateTime", UpdateCheck = UpdateCheck.Never, Expression = "dbo.usrFn_UTCToLocalTime(BirthDate)")]
public System.Nullable<System.DateTime> BirthDate
{
get
{
return this._BirthDate;
}
}
I have also modified the DBML XML as in:
other post on stackoverflow
but also without result.
Is that possible by using LINQ or do I have to overwrite a getter which costs roundtrip to the server?
According to the Remarks section on this MSDN page, the Expression property of the ColumnAttribute is used when calling CreateDatabase, so it won't work the way you intend unless you created your database with Linq to Sql.
You can create a Linq query that selects the various columns and calls the db function in one statement like this (based on MSDN example):
var qry = from person in db.Persons
select new {
FirstName = person.FirstName,
LastName = person.LastName,
BirthDate = person.BirthDate,
Dob = db.usrFn_UTCToLocalTime(person.BirthDate)
};
This projects into an anonymous type, but you could use a non-anonymous type as well. For the sake of the example, I've got a table named Person with FirstName, LastName, and BirthDate columns, and a user defined scalar function named usrFn_UTCToLocalTime. The sql statement sent to the server is:
SELECT [t0].[FirstName], [t0].[LastName], [t0].[BirthDate], CONVERT(DateTime,[dbo].[usrFn_UTCToLocalTime]([t0].[BirthDate])) AS [Dob]
FROM [dbo].[Person] AS [t0]
As I was suggesting in the question, for now I have overwritten the get method so I have:
get
{
using (var context = DB.Data.DataContextFactory.CreateContext())
{
return context.usrFn_UTCToLocalTime(_BirthDate);
}
//return this._BirthDate;
}
But with every access to the property, roundtrip is made - which is not my intention but gives a proper result.
I leave the question still open

NHibernate Like with integer

I have a NHibernate search function where I receive integers and want to return results where at least the beginning coincides with the integers, e.g.
received integer: 729
returns: 729445, 7291 etc.
The database column is of type int, as is the property "Id" of Foo.
But
int id = 729;
var criteria = session.CreateCriteria(typeof(Foo))
criteria.Add(NHibernate.Criterion.Expression.InsensitiveLike("Id", id.ToString() + "%"));
return criteria.List<Foo>();
does result in an error (Could not convert parameter string to int32). Is there something wrong in the code, a work around, or other solution?
How about this:
int id = 729;
var criteria = session.CreateCriteria(typeof(Foo))
criteria.Add(Expression.Like(Projections.Cast(NHibernateUtil.String, Projections.Property("Id")), id.ToString(), MatchMode.Anywhere));
return criteria.List<Foo>();
Have you tried something like this:
int id = 729;
var criteria = session.CreateCriteria(typeof(Foo))
criteria.Add(NHibernate.Criterion.Expression.Like(Projections.SqlFunction("to_char", NHibernate.NHibernateUtil.String, Projections.Property("Id")), id.ToString() + "%"));
return criteria.List<Foo>();
The idea is convert the column before using a to_char function. Some databases do this automatically.
AFAIK, you'll need to store your integer as a string in the database if you want to use the built in NHibernate functionality for this (I would recommend this approach even without NHibernate - the minute you start doing 'like' searches you are dealing with a string, not a number - think US Zip Codes, etc...).
You could also do it mathematically in a database-specific function (or convert to a string as described in Thiago Azevedo's answer), but I imagine these options would be significantly slower, and also have potential to tie you to a specific database.