【问题标题】:Android union queryAndroid联合查询
【发布时间】:2015-06-02 02:28:21
【问题描述】:

我有以下问题: 我有一个名为 planing 的表格,它有以下字段:

idplaning, month, year, shop, target, sales 

所以表格将包含这样的信息(忽略 idplaning):

    month  year  shop       target  sales
-------------------------------------------
     1     2014  ShopName1  3534    122
     2     2014  ShopName1  2323    111
    ...
     12    2014  ShopName1  7865    328
     1     2014  ShopName2  4544    544
     2     2014  ShopName2  5675    642
    ...
     12    2014  ShopName2  4623    323
    ...
     1     2015  ShopName1  3534    122
     2     2015  ShopName1  2323    111
    ...
     12    2015  ShopName1  7865    328
    ... and so on

基本上,该表包含每个商店的每月目标和销售额

我需要在 Listview 中显示如下内容:

shop          Ianuary February March ... November December
----------------------------------------------------------
ShopName1     3534    2323     235       3545     3355
...
ShopNamex     1527    7815     631       556      2754

为了做到这一点(在普通 SQL 中),我可以像这样进行联合:

select shop, sum(Ian), sum(Feb),sum(Mar), sum(Apr), sum(Mai), sum(Iun), sum(Iul), sum(Aug), sum(Sep), sum(Oct), sum(Noi), sum(Decu) from
(
    select shop,target as Ian, 0 as Feb, 0 as Mar, 0 as Apr, 0 as Mai, 0 as Iun, 0 as Iul, 0 as Aug, 0 as Sep, 0 as Oct, 0 as Noi, 0 as Decu from planing where year=2015 and month=1
    union
    ...
    select shop,0 as Ian, 0 as Feb, 0 as Mar, 0 as Apr, 0 as Mai, 0 as Iun, 0 as Iul, 0 as Aug, 0 as Sep, 0 as Oct, 0 as Noi, target as Decu from planing where year=2015 and month=12
) as tbl
group by shop

现在,我的问题是:如何在 Android 中通过 查询方法 使用 SQLite 数据库 ContentProvider 来做到这一点? 我已经为各种常规数据库操作构建了内容提供程序,并且我使用 query 方法(而不是 rawquery

所以我获得了一个常规光标(用于我的 planing 表),如下所示:

String[] col = {MyFirstProvider.RSLDTL_ID_ID,MyFirstProvider.RSLDTL_SHOP, MyFirstProvider.RSLDTL_MONTH, MyFirstProvider.RSLDTL_TARGET, MyFirstProvider.RSLDTL_SALES};
String where = "year=2015";
Cursor cur =  getActivity().getContentResolver().query(MyFirstProvider.CONTENT_URI_RSLDTL, col, where, null, null);

我的问题:如何使用查询方法(not the rawquery)为我的 UNION-Groupped 查询获取游标

请用代码回答。谢谢

编辑 我的 ContentProvider 如下所示:

公共类 MyFirstProvider 扩展 ContentProvider {

static final int DATABASE_VERSION = 7;
private SQLiteDatabase db;
static final String DATABASE_NAME = "myxdb.db";
public static final String TABLE_PLANING = "planing";
...
static final String URLX = "content://" + PROVIDER_NAME + "/planing";
...
public static final Uri CONTENT_URI_PLANING = Uri.parse(URLX);
...
static final int uriCode = 1; // some table
static final int uriCode52 = 53; // planing
static final int uriCode53 = 54; // planing

static final UriMatcher uriMatcher;
private static HashMap<String, String> values;
static {
    uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
    uriMatcher.addURI(PROVIDER_NAME, "planing", uriCode52);
    uriMatcher.addURI(PROVIDER_NAME, "planing/*", uriCode53);
    ...
}

....

 @Override
    public Cursor query(Uri uri, String[] projection, String where, String[] selectionArgs, String sortOrder) {
        SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
        Cursor c;
        switch (uriMatcher.match(uri)) {
            case uriCode:
                qb.setTables(TABLE_NAME);
                qb.setProjectionMap(values);
                c = qb.query(db, projection, where, selectionArgs, null,null, sortOrder);
                break;
            ...
            default:
            throw new IllegalArgumentException("(qry)Unsupported URI: " + uri);
    }
    if (c != null){
       c.setNotificationUri(getContext().getContentResolver(), uri);
    }
    return c;
}

那么我如何在上述方法中实现您的想法?我的意思是如何为我的联合分组复杂查询声明 uriCode?​​p>

【问题讨论】:

  • 嘿 rawQuery 需要两个参数,一个是您的复杂查询,另一个是参数。创建您将在上面展示的您自己的自定义查询?并传递参数。 stackoverflow.com/questions/16136688/….
  • 请不要我的工作来添加您的查询。
  • 我真的认为你误解了我的问题......如果你再看一遍你会注意到我已经有了获取常规查询游标的代码(即使使用 where 子句)。所以这不是我的问题。使用 rawquery 也不是问题。我的问题是如何使用 query 方法为 UNION-ed 分组选择语句实现游标。我粘贴在我的 ContentProvider 的骨架上方,以便您或任何想帮助我的人能够指出添加的位置和添加的内容。我没有找到任何关于在没有 rawQuery 的情况下执行 UNION 的示例
  • K 很抱歉误会了。即使我不知道该怎么做,当涉及到复杂查询时,我总是使用 rawQuery 。请在解决此问题时发布您的答案。再次抱歉。
  • 没关系。让我们希望以前做过这件事的其他人能加入这里,为这件事发光。令人讨厌的是,如此琐碎的事情在任何地方都没有得到彻底的解释......它被宣传使用查询而不是rawquery,但是如果你想使用它......然后自己弄清楚如何去做......真的很烦。如果我能解决它,我会在这里发布完整的答案

标签: android group-by union android-contentprovider


【解决方案1】:

在内容提供程序类中使用 rawquery,您可以在其中使用 uri 覆盖查询方法传递查询方法中的必要列。 并在提供程序类中匹配适当的 uri 并执行您的原始查询方法,您已经有 db 对象。

getActivity().getContentResolver().query(MyFirstProvider.CONTENT_URI_RSLDTL, col, where, null, null);

您可以在哪里检索 col 以及在哪里覆盖查询方法参数。

public class ExampleProvider extends ContentProvider {
....
    public Cursor query(
            Uri uri,
            String[] projection,
            String selection,
            String[] selectionArgs,
            String sortOrder) { ...
            /*
             * Choose the table to query and a sort order based on the code returned for the incoming
             * URI. Here, too, only the statements for table 3 are shown.
             */
            switch (sUriMatcher.match(uri)) {

                  break;

                default:
                ...
                    // If the URI is not recognized, you should do some error handling here.
            }
             /*
         * Gets a writeable database. This will trigger its creation if it doesn't already exist.
         *
         */
        db = mOpenHelper.getWritableDatabase();
        //execute raw query
        db.rawQuery(...);

        }

【讨论】:

  • 如果我这样做了,我可以像普通的简单光标一样访问光标吗?如何在 rawquery 中包含将从查询方法发出的 where 子句和 order by 子句?另外,如何为我的 uriMatcher 声明 uri?
  • 我将对我的问题进行编辑,以描述我当前对 ContentProvider 的方法。请检查并相应地更新您的答案
  • 或者你可以使用 SQLiteQueryBuilder 的 buildUnionQuery 方法
  • 查看我的编辑,您可以在内容提供程序覆盖方法参数中获取 where 子句。或者您可以为 groupby 字段创建自定义 uri 并在需要时提取它。
  • 我知道如何在查询语法中添加 where 子句。我的问题是关于将 where 子句添加到我在 ContentProvider 内的查询覆盖中的 rawquery 中。请查看我的问题编辑以查看我的 ContentProvider,并请解释我应该如何更新其中的查询实现。谢谢
【解决方案2】:

当您想要进行 UNION 查询时,我还没有找到任何方法来使用 query 而不是 rawquery

我认为它目前不存在,因为SQLiteQueryBuilder 类包含构建 UNION 查询的方法,但它不包含任何执行它的方法,我不希望在其他任何地方都可以找到它。

更具体地说,如果您查看SQLiteQueryBuilder 类,您会发现buildUnionQuery 方法返回一个String,并且没有将自定义查询字符串作为参数的query 方法。

也就是说,我在代码中采用的解决方案是这样的:

在您的query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) switch 语句中...

SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
builder.setTables(TABLE_NAME);
HashSet<String> columnsPresentInTable = new HashSet<>(<columns in your table>);
String firstProjection = "shop, target as Ian, 0 as Feb, 0 as Mar, 0 as Apr, 0 as Mai, 0 as Iun, 0 as Iul, 0 as Aug, 0 as Sep, 0 as Oct, 0 as Noi, 0 as Decu";
String firstSelectSubQuery = builder.buildUnionSubQuery(
        null,
        firstProjection,
        columnsPresentInTable,
        0,
        getType(uri),
        selection,
        new String[]{
            String.valueOf(2015),
            String.valueOf(1)
        },
        null
);
[...]
String lastProjection = "shop, 0 as Ian, 0 as Feb, 0 as Mar, 0 as Apr, 0 as Mai, 0 as Iun, 0 as Iul, 0 as Aug, 0 as Sep, 0 as Oct, 0 as Noi, target as Decu";
String lastSelectSubQuery = builder.buildUnionSubQuery(
        null,
        lastProjection,
        columnsPresentInTable,
        0,
        getType(uri),
        selection,
        new String[]{
            String.valueOf(2015),
            String.valueOf(12)
        },
        null
);
String unionQuery = builder.buildUnionQuery(
        new String[]{
            firstSelectSubQuery,
            [...]
            lastSelectSubQuery
        },
        sortOrder,
        null
);
cursor = db.rawQuery(unionQuery, null);

在您看来,这种方法似乎比 rawQuery 更棘手,也许不是您问题的答案,但我正在使用它并推荐它,原因有两个:因为当有一种方法可以做某事时,我总是更喜欢使用它,因为我相信它可以让我支持未来的修改,例如,如果一个查询方法被实现,而且工作量最小。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-11-28
    • 2011-10-04
    • 2013-07-13
    • 1970-01-01
    • 2015-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多