This is for Android SQLite. I have two queries like this:
select * from table where name='name';
and
select * from table where name!='name' order by name;
I want to create a statement which combines these two queries. I tried union all but I can't do order by one statement and then combine. I tried this:
select * from table where name='name'
union all
select * from table where name!='name' order by name;
All it did is to combine the queries and then order by name. I don't want that. I want to do order by on the second statement first and then combine them.
To put the question differently, here is my data:
Name
a
b
c
d
e
f
g
h
i
j
But I want the output to be:
Name
g
a
b
c
d
e
f
h
i
j
I want to get one row to the top and then order the rest of the rows. Any help is appreciated.
No need to use temporary tables, you need to add an additional column to sort on. Something like this:
select 1, * from table where name='name'
union all
select 2, * from table where name!='name'
order by 1, name;
I don't have a sqlite install right now, but this trick should work. (you may have to add an alias to the first column).
Unless there is some other attribute of the table you can use to provide sorting that allows a join between the two selects as in How to combine two sql queries? then I think you'll have to store the result of the query that should float to the top in a temporary table and then add the sorted results to that table before storing it.
I've never used temporary tables in Android so can't provide an example but as far as I'm aware it's possible.
I'd recommend running the two queries separately and then combining the results in code if that's possible in your situation.
According to the SQLLite docs this cannot be done with a UNION or UNION ALL because those operations must be performed on a simple select, (ones without Order by).
http://www.sqlite.org/lang_select.html
There's probably a very clever way to do this that I don't know, which generally leads me to just do two queries and combine the results in java.
[EDIT] And Jhovanny has the very clever way to do it.
Can't test it right now, but something like this should work:
select t.*, case when name = 'name' then 0 else 1 as o from table t order by o, name;
Then you don't have the two selects nor the union. Assuming you can use a case statement in sqlite on android.
Related
I have problem with SQL in Android (SQLite).
I have three tables in relation many-to-many, suppose A, B and C, each has 30 records. I want to join these tables and after that use WHERE clause. I have written something like this code
SELECT *
FROM A
JOIN B ON A.id=B.photoid
JOIN C ON B.urlid=C.id
WHERE C.type=[SOME VALUE]
I have also tried this
SELECT *
FROM A
LEFT OUTER JOIN B ON A.id=B.photoid
LEFT OUTER JOIN C ON B.urlid=C.id AND C.type=[SOME VALUE]
and this
SELECT *
FROM A
CROSS JOIN B
CROSS JOIN C
WHERE A.id=B.photoid AND B.urlid=C.id AND C.type=[SOME VALUE]
These statements don't work in Android. They return 300 records.
What should I change? Is it bug or I do something wrong?
Hard to tell without any additional data, but keep in mind that a JOIN operation will produce a row for each combination of a value in any of the tables involved. If you had 3 tables, each with 30 rows and you wouldn't be filtering any result, it should produce 27000 rows, but you're filtering by A.id=B.photoid and B.urlid=C.id, which might be producing a smaller set of rows.
In my opinion, that's not anything related to SQLite, but to your query instead. I'd try to make your set of values much smaller (for example, 5 per table) and run the same query, and see which results are being returned which shouldn't be, and try to modify your query to make it discard all those unwanted results.
I was wondering if it's possible (it should be) to query multiple tables simultaneously (several at once) in SQLite. Basically I have several tables that have the exact same columns, but the data in them is just organized by the table it's in. I need to be able to use SELECT to get data from the tables (I heard UNION could help), which matches a condition, then group the data by the table it's in.
In other words, would something like this be possible?
SELECT * FROM table1,table2,table3,table4,table5,table6 WHERE day=15 GROUP BY {table}
I'd rather not resort to having to query the tables individually as then I would have a bunch of Cursors that I'd have to manually go through and that would be difficult when I only have one SimpleCursorAdapter? Unless a SimpleCursorAdapter can have several Cursors?
Thanks.
EDIT: The structure of my tables:
Main Table - contains references to subtables in a column "tbls"
and meta-information about the data stored in the subtables
Subtable - contains reference to subsubtables in a column "tbls"
and meta-information about the data stored in the
subsubtables
Subsubtable - contains the actual entries
Basically these tables just make it easier to organize the hierarchical data structure. I suppose instead of having the subsubtables, I could keep the actual entries in the subtable but add a prefix, and have a separate table for the meta-information. It just seems it would be harder to delete/update the structure if I need to remove a level in this data set.
You can create view based on your tables, the query of your view is union of your tables.
create view test as select * from table1 union select * from table2
now you can filter data as you want
for more info check union & view
http://www.w3schools.com/sql/sql_union.asp
http://www.w3schools.com/sql/sql_view.asp
In the end, I decided to forgo having many subsubtables, and instead adding another column like Tim and Samuel suggested. It will probably be more efficient as well then chaining SELECTs with UNION.
i'm writing an Android app and i've run into a bit of a roadblock involving databases. the way Android handles databases, i cannot refer to names in the result set by the usual 'tablename.colname' method, so this presents a huge issue when any tables in the database contain the same column name. what further complicates the issue, is that any table that is used by a ViewAdapter to display the data to the user (as in my application), must contain a field named "_id" as an autoincrement primary key int. therefore, some tables MUST have identical column names. however, to avoid this, it is possible to use an "AS" clause in a statement to rename the value in question. however, i'm using a rather long statement and i don't know how to limit the columns returned on a JOINed table. what i have is this, and it's completely illegal in android due to the 'tablename.colname' references. i actually added the table names in to make the statement more readable, but i can't use them:
SELECT call._id AS android_call_id,
call.phone,
call.time,
call.duration
call.duration_billed
call.pending
call.call_id
call.job_id
FROM call
LEFT OUTER JOIN phone ON call.phone_number=phone.phone
LEFT OUTER JOIN job ON job._id=call.job_id
WHERE call.pending=1 ORDER BY job._id
but what i need, is to rename the job._id to something else using an "AS" statement, same as with the 'call._id' field in the first part of the query. how do i achieve this renaming in a JOIN?
edit:
progress so far. i think i've worked out the syntax errors, but i get another runtime error "no such column 'job._id', which may be related to #Tom H. comment
edit 2:
turns out Tom was right, and i adjusted accordingly, but it doesn't work:
SELECT call._id AS android_call_id,
call.phone,
call.time,
call.duration,
call.duration_billed,
call.pending,
call.call_id,
call.job_id,
job._id AS android_job_id,
job.job_name,
job.job_number
FROM call
LEFT OUTER JOIN phone ON call.phone_number=phone.phone
LEFT OUTER JOIN job ON job._id=call.job_id
WHERE call.pending=1 ORDER BY job._id
error:
05-24 16:50:37.561: ERROR/Minutemaid - Service(7705): oops: ambiguous column name: call._id: , while compiling: SELECT call._id AS android_call_id,call.phone_number,call.time,call.duration,call.duration_billed,call.pending,call.call_id,call.job_id,job._id AS android_job_id,job.job_name,job.job_number FROM call LEFT OUTER JOIN phone ON call.phone_number=phone.phone LEFT OUTER JOIN call ON call.job_id=job._id WHERE call.pending=1 ORDER BY job._id
Can't you simply use AS to alias all of the tablename.columnname references to unique names in the result set?
You can simply create a VIEW that restricts columns selectable in a table and assigns another name to them.
You can try massaging the table names before you join them by using sub-queries with AS in the FROM clause. For example:
select c_phone, c_id, p_id
from (select id as c_id, phone as c_phone, phone_number as c_phone_number, ... from call) as c
left outer join (select id as p_id, phone as p_phone, ... ) as p
on c_phone_number = p_phone
...
If the limitation is just that you can't use table names to distinguish between columns but can use correlation names then simpler is:
select c.id, c.phone, p.id as "p_id" from ... call c join phone p
Let's say an SQLite database column contains the following value:
U Walther-Schreiber-Platz
Using a query I'd like to find this record, or any similar records, if the user searches for the following strings:
walther schreiber
u walther
walther-schreiber platz
[Any other similar strings]
However I cannot figure out any query which would do that. Especially if the user does not enter the - character.
Example:
select * from myTable where value like '%walther schreiber%'; would not return the result because of the missing -.
Thanks,
Robert
So, as I said in my comment, I think you can have a query along the lines of:
select * from myTable where LOWER(value) like <SearchValue>
I'm assuming you're collecting the <SearchValue> from the user programmatically, so would be able to do the following: <SearchValue> would need to be: The user's search string, appropriately cleansed to avoid SQL injection attacks, converted to lower case, with all of the spaces converted to '%', so that they match zero or more characters...
So you would have (for example):
select * from myTable where LOWER(value) like '%walther%schreiber%'
select * from myTable where LOWER(value) like '%walther-schreiber%platz%'
etc... however, this does assume that the word order is the same, which in your examples it is...
I've a column in which contains numbers or strings. The type of the column is varchar.
Usually when we sort it using the string field, then all the numbers come first and then strings start. But I want all the strings first and then numbers.
TIA !
You'll have to write it in two separate queries. One for selecting numbers, the other for strings. Preferably I would create a second column (one for numbers, one for strings), making it easier and faster to have those two queries run.
This worked for me...
Select * from Table order by stringfield+0;
edit: http://www.sqlite.org/datatypes.html (Point 4.0)
UPDATE: Try this....
select * from Table where LENGTH(trim(stringfield,"0123456789 ") )=0 union select * from table order by stringfield;
How about the following (two queries as suggested above):
select * from Table where LENGTH(trim(stringfield,"0123456789 ")) > 0; select * from table where LENGTH(trim(stringfield,"0123456789 ")) = 0;
The first select should return only values that are not numeric, whilst the second should return only values that are numeric.
For a table that contains a mixture of numeric and string data, this outputs the strings first, then the numbers.
Have you considered creating a custom collation-function? I have never used this myself, but it sounds like exactly what you need.