3

学習ツールとしてアプリを作成していますが、結合クエリに問題があります。

次のように宣言された馬とカバーの2つのテーブルを持つデータベースがあります。

    private static final String HORSES_CREATE = "create table horses (_id integer primary key autoincrement, "
        + "name text not null, type integer not null, birthDate text not null, vaccineDate text not null, "
        + "inFoal integer not null, notes text not null);";

「タイプ」フィールドは、種牡馬、牝馬、去勢馬などを指し、スピナーから選択されます (XML 文字列配列から取り込まれます)。

private static final String COVERS_CREATE = "create table covers (_id integer primary key autoincrement, "
        + "stallionName integer not null, mareName integer not null, firstCoverDate text not null, lastCoverDate text not null, "
        + "scan14Date text not null, scan28Date text not null, foalingDate text not null, inFoal integer not null, notes text not null);";

StallionName は、実際には horse テーブルの馬の _id フィールドとして格納されます。これは、馬のテーブルでタイプが「Stallion」として定義されている馬のみを表示するスピナーから選択されます。(マーレも同様)。

テーブルを作成およびアップグレードするためのクラス「DatabaseHelper」があり、各テーブルには独自のアダプタークラス「horsesDbAdapter」および「coversDbAdapter」があり、エントリを追加、編集、削除するメソッドと関連するクエリが含まれています。(fetchAllHorses()、fetchHorse(long rowId) )

例えば:

    public Cursor fetchAllHorses() {

    return mDb.query(DATABASE_TABLE,
            new String[] { KEY_ROWID, KEY_NAME, KEY_TYPE, KEY_BIRTHDATE,
                    KEY_VACCINEDATE, KEY_INFOAL, KEY_NOTES }, null, null,
            null, null, null);
}

(これはすべて Android のメモ帳の例を基にしています)

カバー テーブルの内容をリストビューに表示しています (stalionName と mareName のみを表示しています)。しかし、これらのフィールドには horses テーブルへの一意の参照が含まれているだけなので、表示されるのはかなり情報量の少ない _id フィールドだけです。

私の質問は; listView に表示する馬に関連する名前を取得するにはどうすればよいですか? 結合クエリなどを読みましたが、それらを実装しようとすると迷子になります。horses._id と covers.stallionName に参加する必要があると思います (その後、MareName とほぼ同じものを作成します) が、これを行う方法の具体的な例が見つかりません。

追加情報/コードが必要な場合はお知らせください。

どんな助けでも大歓迎です、事前に感謝します。

編集: horses テーブルで (_id) を参照する StallionName と mareName の外部キーを作成しましたが、結合クエリを実装する方法と場所がまだわかりません。horsesDbAdapter、coversDbAdapter、または coversList クラスにある必要がありますか? (coversList は、listView を作成して設定するクラスです) カバー テーブルの宣言は次のようになります。

    private static final String COVERS_CREATE = "create table covers (_id integer primary key autoincrement, "
        + "stallionName integer not null, mareName integer not null, firstCoverDate text not null, lastCoverDate text not null, "
        + "scan14Date text not null, scan28Date text not null, foalingDate text not null, inFoal integer not null, notes text not null," +
        "FOREIGN KEY (stallionName) REFERENCES horses (_id), FOREIGN KEY (mareName) REFERENCES horses (_id));";
4

2 に答える 2

9

私は Android と SQLLiteHelper の初心者で、同じことを考えていました。

この投稿を読んだ後、テーブル間の結合を定義する方法はメソッドで行われることがわかりましたSQLLiteQueryBuilder.setTablesここの参照を参照してください

こちらのブログから頂きました

これが読者を正しい方向に向けるのに役立つことを願っています.

于 2012-10-03T01:34:22.463 に答える
2

私はそれを機能させることができました。同様の問題を抱えている可能性のある他の人のために、私がしたことを詳しく説明します。@deceiverが述べたように、馬を参照するstallionNameとmareNameの外部キーを作成する必要がありました(編集を参照)。

coversList クラス (listView を実装するクラス) では、データベースのインスタンスを取得し、rawQuery を使用して SQL コードを直接実装する必要がありました (Query を使用してそれを行うことは可能かもしれませんが、方法はわかりません)。追加されたコードは次のとおりです。

private Cursor coversCursor;
private void fillData() {

    db = (new DatabaseHelper(this).getReadableDatabase());
    coversCursor = db.rawQuery("SELECT horses1.name AS stallionNameText, covers.*, horses2.name AS mareNameText FROM horses horses1 JOIN covers ON horses1._id = covers.stallionName JOIN horses horses2 ON horses2._id = covers.MareName",
                    null);
    startManagingCursor(coversCursor);
    // Create an array to specify the fields we want to display in the list
    // (the renamed fields from the above query)
    String[] from = new String[] { "stallionNameText", "mareNameText" };

    // and an array of the fields we want to bind those fields to (in this
    // case just text1)
    int[] to = new int[] { R.id.rowStallionName, R.id.rowMareName };

    // Now create a simple cursor adapter and set it to display
    SimpleCursorAdapter covers = new SimpleCursorAdapter(this,
            R.layout.covers_list_row, coversCursor, from, to);
    setListAdapter(covers);
}

その後、onCreate() メソッドで FillData() が呼び出されます。次に、onDestroy メソッドでデータベースを閉じます。(ここでは、covers テーブルからすべての列を選択するのは無駄に思えますが、最終的にはこれらの列を listView にも表示します。コーディングを続行する前にこれに答えたかっただけです)。私が役に立つと思ったチュートリアルはhttp://coenraets.org/blog/android-samples/androidtutorial/でした

同じテーブルを参照する 2 つの外部キーがあり、listView に種馬の名前と牝馬の名前の両方を表示する必要があったため、SQL クエリに問題がありました。そのため、2 つの馬のテーブルをカバー テーブルに結合する必要がありました。SQL クエリの FROM セクションでテーブルの名前を変更する必要がありました。うまくいけば、上記のコードは明確です。そうでない場合は、次のものが役立つことがわかりました。http://www.bryantwebconsulting.com/blog/index.cfm/2005/3/11/join_a_table_to_itself_in_sql

この説明が私の (異常な) 例に固有すぎる場合は申し訳ありません。読んでくれてありがとう。

于 2012-07-06T11:32:11.153 に答える