【问题标题】:What is the best way to do SELECT in SQLite with equals subqueries使用等于子查询在 SQLite 中执行 SELECT 的最佳方法是什么
【发布时间】:2013-07-31 08:00:55
【问题描述】:

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

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

【问题讨论】:

    标签: android sqlite android-sqlite android-cursor


    【解决方案1】:

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

    使用以下数据作为输入:

    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. 1234563避免超出良好的数据库设计。
    3. 仅供参考:这根本不重要,但类型并不是真正的描述性,列名应该是描述性的,所以类型应该是 type_ofwhat,但前提是您想遵循良好的数据库设计。

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

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

    希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 2020-01-09
      • 2021-08-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-01
      • 1970-01-01
      • 2014-04-20
      相关资源
      最近更新 更多