I have a query that I am using to make a leader board for an android application that will grab data out of an Sql database and order by score. Although with this I want to add the rankID which is a primary field as a positional value in this leader board. How would I go about doing this so I have it ordered by score and have positions in descending order?
String selectQuery = "SELECT rankID, firstName, lastName, score " +
"FROM leader " +
"ORDER BY score DESC " +
"LIMIT 10";
In mysql
SELECT #rankID:= #rankID +1, firstname, lastname, score
FROM leader,
(SELECT #rankID:= 0) r
ORDER BY score DESC
LIMIT 0,10;
I would probably just loop it myself in my code and use that as my counter instead of doing it this way though.
Here you're misplacing the order by columns. If you require ordering by KEYWORD_TEXT then by BID_AMOUNT and CITY (if yes then)
Change order by as:
ORDER BY KEYWORD_TEXT, BID_AMOUNT CITY
Related
Is it possible to sort the results alphabetically and then numerically when pulling data from the Contacts table?
Code snippet:
cursorLoader.setSortOrder(
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC, " +
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " ASC, " +
ContactsContract.CommonDataKinds.Phone.IS_SUPER_PRIMARY + " DESC, " +
ContactsContract.CommonDataKinds.Phone.IS_PRIMARY + " DESC");
This results in numerical values appearing before alphabetical values
If you mean that the display name can contain numbers and names and you want the numbers to appear last e.g.
And you want Fred to appear before 01 23456 7890 but say for Alan to appear before Fred then one way would be to introduce a means of detecting whether or not the value is a number. This can be accomplished by trying to convert the value to a number (integer in this example) using a CAST.
So instead of :-
SELECT * FROM phonedata ORDER BY display_name ASC, contact_id ASC, is_super_primary DESC, is_primary DESC
which results in :-
You could use something along the lines of :-
SELECT
CAST(replace(display_name,' ','') AS INTEGER) AS converted,
*
FROM phonedata
ORDER BY CAST(replace(display_name,' ','') AS INTEGER) ASC,
display_name ASC,
contact_id ASC,
is_super_primary DESC,
is_primary DESC
This would produce :-
Notes
The converted column has been included for illustration.
That is it shows how an alphabetic value will result in 0 from the CAST, thus making it top order for the sort, whilst a numeric value (except 0)
You may need to tailor the above but basically the principle applies
I have the following table:
String sqlStatement = "CREATE TABLE " + CallsEntry.TABLE_NAME + "(";
sqlStatement += CallsEntry.FIELD_CALL_ID + " INT PRIMARY KEY DESC,";
sqlStatement += CallsEntry.FIELD_CALLER_PHONE + " TEXT,";
sqlStatement += CallsEntry.FIELD_INSERTION_DATE_MILLIS + " INT); COMMIT;";
db.execSQL(sqlStatement);
Please note that the primary key is descending.
Then I expect from my experience with SQL server that the following query will yield the records in an descending order:
SELECT * FROM tblCalls;
However, this is not the case. I'm getting the records in ascending order. I have to use this:
SELECT * FROM tblCalls ORDER BY CallId DESC;
Why is that? Can I do something differently and get the records in descending order?
There is no such thing as default key order in SQLite.
Depends on documentation:
If a SELECT statement that returns more than one row does not have an
ORDER BY clause, the order in which the rows are returned is
undefined. Or, if a SELECT statement does have an ORDER BY clause,
then the list of expressions attached to the ORDER BY determine the
order in which rows are returned to the user.
So default order is underfined without ORDER BY clause.
Does this produce the right order?
SELECT CallId FROM tblCalls
I had following Table
CREATE TABLE Customer
( `Name` varchar(7), `Address` varchar(55), `City` varchar(15),`Contact` int,`timestamp` int)
;
INSERT INTO Customer
(`Name`,`Address`, `City`, `Contact`,`timestamp`)
VALUES
('Jack','New City','LA',79878458,456125),
('Joseph','New Lane23','LA',87458458,794865),
('Rosy','Old City','Paris',79878458,215125),
('Maria','New City','LA',79878458,699125),
('Jack','New City','LA',79878458,456125),
('Rosy','Old City','Paris',79878458,845125),
('Jack','New Main Street','New York',79878458,555525),
('Joseph','Near Bank','SAn Francisco',79878458,984521)
;
I want to get all customer record with highest timestamp without duplication.
Try the following.
select name,max(timestamp),Address,City,Contact from Customer group by name
I want to get all customer record with highest timestamp without
duplication.
Use DISTINCT operator and ORDER BY clause like
select distinct `Name`,`Address`, `City`, `Contact`,`timestamp`
from customer
order by `timestamp` desc;
In that case you can use JOIN query like
select t1.*
from customer t1 join
(select Name, max(`timestamp`) as maxstamp
from customer
group by Name) xx
on t1.Name = xx.Name
and t1.`timestamp` = xx.maxstamp;
Try this:
SELECT * FROM `customer`
group by name,Address,City,Contact,timestamp
order by timestamp desc
I'm joining the Customer table with itself, the condition c1.timestamp<c2.timestamp on the join clause combined with c2.timestamp IS NULL
will make sure that only the latest record for each person is returned. I put DISTINCT because on your sample data there are two records for Jack with the same timestamp:
SELECT DISTINCT
c1.*
FROM
Customer c1 LEFT JOIN Customer c2
ON c1.Name=c2.Name
AND c1.Contact=c2.Contact -- you might want to remove this
AND c1.timestamp<c2.timestamp
WHERE
c2.timestamp IS NULL
ORDER BY
Name, Address
Please see a fiddle here.
I'm using SQLite on Android using SQLiteDatabase (http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html)
I am developing a bible application, which has a single table with the following columns:
book : int
chapter : int
verse : int
wordIdx : int
strongId : string
word : string
each sentence is broken down in to a series of strongId/word pairs, so wordIdx is used to order the words, strongId is simply a index in to a concordance, and word is the word in the sentence.
so I have 300,000 rows
the bottleneck appears to be my query to get a list of words for each verse:
My SQL is effectively this:
SELECT strongId, word FROM ? WHERE book=? AND chapter=? AND verse=?
Here is the code:
Cursor cursor = mBible.database().rawQuery("SELECT " + KEY_STRONGID + "," + KEY_WORD + " FROM " + tableName() + " WHERE " + KEY_BOOK + "=? AND " + KEY_CHAPTER + "=? AND " + KEY_VERSE + "=?" , new String[] { String.valueOf(mChapter.mBook.index()), String.valueOf(mChapter.index()), String.valueOf(verse) });
cursor.moveToFirst();
mWordList = new ArrayList<Word>();
do {
mWordList.add(new Word(cursor.getString(1), cursor.getString(0)));
} while (cursor.moveToNext());
Now, I've tried putting each chapter in to its own temporary view (using CREATE TEMP VIEW) which cuts down the records to about 400 in my example how ever it is still taking far to long to query
Its taking of the order of 30 seconds to generate the text for two chapters to display to the user (using a temporary view and without using a temporary view). It takes about 5 seconds if I set up a dummy list of words to avoid the database query.
How can I improve the performance of this? It seems as if a temp view is having no impact on performance as I had hoped.
A view does not change the performance of a query; it just saves the query itself, not the results of the query.
If you open your database with the sqlite3 command-line tool on your desktop machine, you can use the EXPLAIN QUERY PLAN command to check how efficient your queries are.
Without any indexes, you query always scans the entire table:
> sqlite3 bible.db
SQLite version 3.7.15.2 2013-01-09 11:53:05
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> EXPLAIN QUERY PLAN SELECT strongId, word FROM MyTable WHERE book=1 AND chapter=2 AND verse=3;
0|0|0|SCAN TABLE MyTable (~1000 rows)
With an index on your three lookup fields, SQLite can do a fast search in the index and needs to read only the matching records from the table:
sqlite> CREATE INDEX b_c_v ON MyTable(book, chapter, verse);
sqlite> EXPLAIN QUERY PLAN SELECT strongId, word FROM MyTable WHERE book=1 AND chapter=2 AND verse=3;
0|0|0|SEARCH TABLE MyTable USING INDEX b_c_v (book=? AND chapter=? AND verse=?) (~8 rows)
If you create a covering index (with all fields used in the query, lookup fields first), SQLite does not need to read from the table at all. However, this does not give a big speedup over a normal index, and might not be worth the additional storage cost:
sqlite> CREATE INDEX cov ON MyTable(book, chapter, verse, strongId, word);
sqlite> EXPLAIN QUERY PLAN SELECT strongId, word FROM MyTable WHERE book=1 AND chapter=2 AND verse=3;
0|0|0|SEARCH TABLE MyTable USING COVERING INDEX cov (book=? AND chapter=? AND verse=?) (~8 rows)
Please note that SQLite can use at most one index per table in a query, so it does not always make sense to create multiple indexes.
Use EXPLAIN QUERY PLAN to check which indexes are actually used, and whether you can create a few indexes to optimize most of your queries.
Also see the Query Planning documentation.
I ended up creating temporary tables and performance is now acceptable
I have a database saved in my Android application and want to retrieve the last 10 messages inserted into the DB.
When I use:
Select * from tblmessage DESC limit 10;
it gives me the 10 messages but from the TOP. But I want the LAST 10 messages. Is it possible?
Suppose the whole table data is -
1,2,3,4,5....30
I wrote query select * from tblmessage where timestamp desc limit 10
It shows 30,29,28...21
But I want the sequence as - 21,22,23...30
Change the DESC to ASC and you will get the records that you want, but if you need them ordered, then you will need to reverse the order that they come in. You can either do that in your own code or simply extend your query like so:
select * from (
select *
from tblmessage
order by sortfield ASC
limit 10
) order by sortfield DESC;
You really should always specify an order by clause, not just ASC or DESC.
on large databases, the ORDER BY DESC statement really might slow down the system, e.g. raspberry pi. A nice approach to avoid ORDER BY is the OFFSET command. And you even keep the stored order:
SELECT * FROM mytable LIMIT 10 OFFSET (SELECT COUNT(*) FROM mytable)-10;
see: http://www.sqlite.org/lang_select.html
check out your performance with:
.timer ON
Slightly improved answer:
select * from (select * from tblmessage order by sortfield DESC limit 10) order by sortfield ASC;
Michael Dillon had the right idea in his answer, but the example gives the first few rows, inverted order:
select * ... (select * ... ASC limit 10) ... DESC
He wanted the last, it should be:
select * ... (select * ... DESC limit 10) ... ASC
Try this,
SQLiteDatabase database = getReadableDatabase();
Cursor c=database.rawQuery("sql Query", null);
if(c.moveToFirst) {
int curSize=c.getCount() // return no of rows
if(curSize>10) {
int lastTenValue=curSize -10;
for(int i=0;i<lastTenValue;i++){
c.moveToNext();
}
} else {
c.moveToFirst();
}
}
Then retrieve the last 10 data.
If your table contains a column with primary key autoincrement (some "row_id" for example) then you just need single select with DESC order by this column
Raw request looks like
select * from table_name order by row_id DESC limit 10
Android implementation is
private Cursor queryLastEvents() {
return getDatabase().query("table_name", null, null, null, null, null, "row_id DESC", "10");
}
"SELECT * FROM( SELECT * FROM " + tablename + whereClause + " ORDER BY timestamp DESC LIMIT 10) ORDER BY timestamp ASC";
In your query, the DESC is interpreted as a table alias.
As mentioned by ρяσѕρєя K, to be able to specify a sorting direction, you need to sort in the first place with an ORDER BY clause.
The column to be sorted should be a timestamp, if you have one, or an autoincrementing column like the table's primary key.
select * from
(select * from table_name order by yourfield ASC limit 10)
order by yourfield DESC;
You cannot have better solutions than this.
cursor.moveToLast();
while (cursor.moveToPrevious()){
//do something
}
with same query: select * from tblmessage where timestamp desc limit 10