0

我用很少的子查询和联合进行大查询:

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 - 它工作错误。因为没有调用临时表的重新创建。

如何在游标的同一查询中执行一个子查询或一个临时表?

4

1 回答 1

0

我不确定您的最终目标是什么,但我能够将您的第一个查询转换为相关查询。如果来自主查询的列的值,那是子选择获取的地方。关键是主查询列必须始终在子选择中比较运算符的右侧,所以我颠倒了日期并切换了比较运算符。

使用以下数据作为输入:

1 1 1 注 1 1 20130601 6100 1 1 0 201306

2 2 2 注 2 2 20130701 72013 0 1 0 201307

3 3 3 注 3 3 20130715 4201 1 1 a 0 201307

4 3 3 注 4 4 20130318 68010 1 1 0 201303

5 1 1 注释 5 5 20130615 37077 1 1 0 201306

我无法使用正在使用的工具复制 strftime,所以我添加了最后一列 ym,我相信这相当于你的 strftime 为你的 group by 的结果。

这是我想出的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 as _id and id”,除了你几乎是冗余的,将来只使用_id。任何维护代码的人都会更快地理解它。通过 android 方法绕过 _id 要求的好方法。

  2. 'sum' 和 'date' 的列名也可能存在问题,因为它也是一个 sql 函数,或者可能是,或者是某种语言的保留字,如果不是,我会避免使用良好的数据库设计.

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

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

    1. 这两个查询可能可以合二为一,我再次需要知道结果和其中所有列的真正意图是什么。

希望这可以帮助。

于 2013-07-31T00:00:55.343 回答