我使用少数子查询和联合进行大查询:
public Cursor getCursor(int outlayType, long carId){
String selection;
String[] selectionArgs;
if(outlayType>0){
selection = "car_id=? and type=?";
selectionArgs = new String[]{
Long.toString(carId),Integer.toString(outlayType),
Long.toString(carId),Integer.toString(outlayType),
Long.toString(carId),Integer.toString(outlayType)};
}else{
selection = "car_id=?";
selectionArgs = new String[]{Long.toString(carId), Long.toString(carId), Long.toString(carId)};
}
String sql = "select (select count(*)+1 from outlays b where a.date < b.date and "+selection+") as countNum," +
" id as _id, id, type, note, sum, date," +
" odometer, unread, future, input_type, 0 as row_type " +
" from outlays a where "+ selection +" " +
" union " +
" select 0, 0, 0, 0, '', sum(sum), max(date)+2," +
" 0, 0, 0, '', 1 as row_type" +
" from outlays where "+ selection +" group by strftime('%Y-%m', date/1000, 'unixepoch')" +
" order by 7 DESC";
return sqdb.rawQuery(sql, selectionArgs);
}
它很完美,但是......
你可以看到:我几次使用相同的WHERE条件。这不是结束。查询将会增长。这种情况将一次又一次地使用。
我想像这样使用临时表:
public Cursor getCursor(int outlayType, long carId){
String selection;
String[] selectionArgs;
if(outlayType>0){
selection = "car_id=? and type=?";
selectionArgs = new String[]{Long.toString(carId),Integer.toString(outlayType)};
}else{
selection = "car_id=?";
selectionArgs = new String[]{Long.toString(carId)};
}
sqdb.execSQL("drop table if exists sub");
sqdb.execSQL("create temp table sub " +
"as select * from outlays where "+selection, selectionArgs);
String sql = "select (select count(*)+1 from sub b where a.date < b.date) as countNum," +
" id as _id, id, type, note, sum, date," +
" odometer, unread, future, input_type, 0 as row_type " +
" from sub a " +
" union " +
" select 0, 0, 0, 0, '', sum(sum), max(date)+2," +
" 0, 0, 0, '', 1 as row_type" +
" from sub group by strftime('%Y-%m', date/1000, 'unixepoch')" +
" " +
" order by 7 DESC";
return sqdb.rawQuery(sql, null);
}
它看起来更好(对我来说),但是当我调用Cursor.notifyDataSetChanged时 - 它的工作错误。因为不调用临时表的重新创建。
如何在Cursor的同一查询中执行一个子查询或一个临时表?
答案 0 :(得分:0)
我不确定您的最终目标是什么,但我能够将您的第一个查询转换为相关查询。这是subselect获取主查询中列的值的位置。关键是主查询列必须始终位于子选择中比较运算符的右侧,因此我颠倒了日期并切换了比较运算符。
使用以下数据作为输入:
1 1 1 note 1 1 20130601 6100 1 1 0 201306
2 2 2 note 2 2 20130701 72013 0 1 0 201307
3 3 3 note 3 3 20130715 4201 1 1 a 0 201307
4 3 3 note 4 4 20130318 68010 1 1 0 201303
5 1 1 note 5 5 20130615 37077 1 1 0 201306
我无法使用该工具复制strftime所以我添加了最后一列ym,我相信这相当于你的团队的strftime结果。
这是我提出的SQL:
select (select count(*)+1 from outlays b where b.date1 > a.date1 and b.car_id=a.car_id) as countNum,
id as _id, a.id, a.type, a.note, a.sum1, a.date1, a.odometer, a.unread, a.future, a.input_type, 0 as row_type, ym
from outlays a where car_id= 1
union all
select 0, 0, 0, 0, '', sum(sum1), max(date1)+2, 0, 0, 0, ' ', 1 as row_type, ym from outlays group by ym order by 7 DESC;
有数据结果:
#| |.|.|.|. |.|. |. |.|.|.|.|.
-+-+-+-+-+------+-+--------+-----+-+-+-+-+------
1|0|0|0|0| |5|20130717|0 |0|0| |1|201307
2|0|0|0|0| |6|20130617|0 |0|0| |1|201306
3|1|5|5|1|note 5|5|20130615|37077|1|1| |0|201306
4|2|1|1|1|note 1|1|20130601|6100 |1|1| |0|201306
5|0|0|0|0| |4|20130320|0 |0|0| |1|201303
注意在这个特殊情况下,直到我真正了解目标,可以使用UNION或UNION ALL。
我注意到的一些事情并在上面改变了一些:
这里可能没有列名称问题&id; id为_id和id&#39;除了你几乎是还原剂之外,将来只需使用_id。任何维护代码的人都会更快地理解它。通过android方法绕过_id要求的好方法。
还有一个问题可能是列名为&#39; sum&#39;和&#39; date&#39;因为它也是一个sql函数或者可能是某个语言中的保留字,如果没有,我会避免使用好的数据库设计。
仅供参考:并不是说这一点很重要,但类型并不是真正具有描述性的,列名应该是描述性的,所以type应该是type_ofwhat,但只有当你想要遵循良好的数据库设计时才是。
此外,由于我不知道您的意图,我不确定您是否还想要分组其他列。根据我的经验,通常有。
希望这有帮助。