使用equals子查询在SQLite中执行SELECT的最佳方法是什么

时间:2013-07-10 11:28:03

标签: android sqlite android-sqlite android-cursor

我使用少数子查询和联合进行大查询:

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的同一查询中执行一个子查询或一个临时表?

1 个答案:

答案 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。

我注意到的一些事情并在上面改变了一些:

  1. 这里可能没有列名称问题&id; id为_id和id&#39;除了你几乎是还原剂之外,将来只需使用_id。任何维护代码的人都会更快地理解它。通过android方法绕过_id要求的好方法。

  2. 还有一个问题可能是列名为&#39; sum&#39;和&#39; date&#39;因为它也是一个sql函数或者可能是某个语言中的保留字,如果没有,我会避免使用好的数据库设计。

  3. 仅供参考:并不是说这一点很重要,但类型并不是真正具有描述性的,列名应该是描述性的,所以type应该是type_ofwhat,但只有当你想要遵循良好的数据库设计时才是。

  4. 此外,由于我不知道您的意图,我不确定您是否还想要分组其他列。根据我的经验,通常有。

    1. 这两个查询可能是一个,我再次需要知道结果及其中所有列的真实意图。
  5. 希望这有帮助。