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 を呼び出すと、正しく動作しません。一時テーブルの再作成が呼び出されないためです。

Cursor の同じクエリで 1 つのサブクエリまたは 1 つの一時テーブルを実行するにはどうすればよいですか?

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 を追加しました。これは、グループ by の 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 as _id and id」という列名の問題はおそらくありませんが、ほとんど冗長であることを除いて、将来は_idを使用するだけです。コードを維持している人は、コードを少し早く理解できるようになります。Android メソッドによって _id 要件を回避する良い方法です。

  2. また、おそらく「sum」と「date」の列名にも問題があります。これは、SQL 関数であるか、そうである可能性があるため、または一部の言語の予約語であり、そうでない場合は、適切なデータベース設計を回避するだけです.

  3. 参考:これはまったく問題ではありませんが、タイプは実際には説明的ではありません。列名は説明的であるべきなので、タイプは type_ofwhat にする必要がありますが、それは適切なデータベース設計に従いたい場合に限られます。

  4. さらに、あなたの意図を知らなかったので、グループ化する他の列があるかどうかもわかりませんでした。私の経験から、通常はあります。

    1. 2 つのクエリを 1 つにすることもできますが、結果とその中のすべての列の本当の意図を知る必要があります。

お役に立てれば。

于 2013-07-31T00:00:55.343 に答える