如何使用多个结果遍历连接表?

时间:2012-12-10 14:15:32

标签: android sql database sqlite join

我有3个表格,USERENTRY(对于输入的产品,不是创建PRODUCT表所必需的)和USER_COLLECTION,这是USER之间的表格和ENTRY,因为一个条目可以有多个用户。

基本上:

用户= USERID | USER_NAME

条目= ENTRYID | ENTRY_NAME | ENTRYPRICE | ENTRY_DATE

Collection = COLLECTIONID | ENTRYID | USERID

我有一个用户表,在整个项目中都存在。他们可以创建条目(通常是某种价格的产品),并且可以将多个用户链接到某个条目(可以从列表中选择,因此用户可以在整个项目中保留)。

例如,我的表格如下:

User
--------------------------
user_id   |   user_name
--------------------------
   1      |    'FOO'
   2      |    'BAR'
   3      |    'FOOBAR'


ENTRY
-----------------------------------------------------------------------
entryid  |   entry_name     |  entry_price |      entry_date     
-----------------------------------------------------------------------
   0     |    'Banana'      | 2.50         |  12/12/2012


COLLECTION
---------------------------------------
collectionid |   entryid    |  userid     
----------------------------------------
   0         |    1         | 1
   1         |    1         | 2
   2         |    1         | 3

我有一个Banana,价格为2.50,有3个用户链接到它,Foo,Bar和Foobar。

现在,我想在我的应用程序中使用它并获取数据;除了我不知道从哪里开始。我尝试选择条目数据,使用该id循环收集数据,但这意味着我有两个游标打开,它将无法正常工作。尝试创建一个连接,但我真的不能做一个好的,主要是因为:

JOIN
---------------------------------------
collectionid |   entryname |  username
----------------------------------------
   0         |    Banana   | FOO
   1         |    Banana   | BAR
   2         |    Banana   | FOOBAR

我无法迭代这一点,因为我会在Android代码中创建多个相同的条目对象...

希望我明白这一点。

if (cursor2.moveToFirst()) {
    do {
        Item i = new Item(<GET STUFF FROM CURSOR>);
        i.addUser(new Person(<GET STUFF FROM CURSOR>)));
        Log.d("TAG", i.getUsersPaying().size() + "");
    } while (cursor2.moveToNext());
}

如果我使用它,我会创建Item i的多个实例。他们都是香蕉,而我只有1个项目香蕉,并添加了多个用户。

2 个答案:

答案 0 :(得分:2)

首先,您可能需要考虑在连接查询中返回表中的ID。如果您返回entryid列,事情就会容易一些。

只需制作一个Map<Integer, Item>来存储您已经在循环中看到的项目。在检查每个光标时,请检查地图以查看是否已有实例。如果不这样做,只需制作一个新的并插入即可。

假设您的查询结果为:

JOIN
----------------------------------------------------
collectionid |   entryname |   entryname |  username
----------------------------------------------------
   0         |    1        |    Banana   | FOO
   1         |    1        |    Banana   | BAR
   2         |    1        |    Banana   | FOOBAR
   2         |    2        |    Apple    | FOOBAR

您可以按如下方式修改代码:

Map<Integer, Item> items = new HashMap<Integer, Item>();
if (cursor2.moveToFirst()) {
    do {
        int itemId = cursor2.getInt(1);
        Item i;
        if (items.containsKey(itemId))
            i = items.get(itemId);
        else
        {
            i = new Item(<GET STUFF FROM CURSOR>);
            items.put(itemId, i);
        }
        i.addUser(new Person(<GET STUFF FROM CURSOR>)));
        Log.d("TAG", i.getUsersPaying().size() + "");
    } while (cursor2.moveToNext());
}

答案 1 :(得分:1)

您需要维护已加载到内存中的实体的字典。例如,在一个可以保留的背景片段中。

基本上你会这样做:

Item i = cacheFragment.createOrGetEntry( cursor.getLong( ENTRY_ID_COLUMN_INDEX ) );
Person p = cacheFragment.createOrGetPerson( cursor.getLong( PERSON_ID_COLUMN_INDEX ) );

当然,您的查询还必须返回您需要的所有行的ID(entryId和personId)。但是连接查询是有效地执行此操作的方法,因此请保留您对此所做的操作,并添加两个缺少的ID列。

createOrGetPerson方法如下所示:

public Person createOrGetPerson(long id) {
    Entry<Long, Person> p = personDictionnary.get( id ); // can be a HashMap or even better, a SparseArray
    if (p==null) {
      p = new Person(id);
      personDictionnary.put(p); // Remember it for next time
    }
    return p;
}

你还应该看一下处理这类问题的数据持久性框架或ORM框架(例如Hibernate,即使我不知道这是否适用于Android)。