使用SQLiteQueryBuilder buildUnionSubQuery()方法

时间:2014-12-03 20:10:25

标签: android android-sqlite

我有两个表如下所示:

Table1

_id | _key | _mime_type | _hash
---------------------------

Table2

_id | _path | _mimetype
-------------------

我可以通过我的内容提供程序query()方法中的以下命令执行UNION查询来获取带有结果集的有效游标:

String unionQuery = " SELECT "
                        + Table1._ID + " AS _id, "
                        + Table1.QUICK_KEY + " AS _key, "
                        + Table1.MIME_TYPE + " AS _mime,"
                        + Table1.HASH + " AS _hash,"
                        + "NULL as _path_to_file"
                        + " FROM " + Table1
                        + " UNION "
                        + " SELECT "
                        + Table2._ID + " AS _id, "
                        + "NULL AS _key, "
                        + Table2.MIME_TYPE + " AS _mime,"
                        + "NULL AS _hash,"
                        + Table2.PATH + " as _path_to_file"
                        + " FROM " + Table2;

                return db.rawQuery(unionQuery, null);

我不想手动编写上面的语句,而是使用SQLiteQueryBuilder类中的buildUnionSubQuery()方法。

buildUnionSubQuery()文档位于http://developer.android.com/reference/android/database/sqlite/SQLiteQueryBuilder.html

我一直在尝试使用该方法,但是在创建我手动编写的SQL语句时没有运气。

我尝试的代码的一个例子(我尝试了大约10种不同的东西)是:     SQLiteQueryBuilder cloudQueryBuilder = new SQLiteQueryBuilder();                     SQLiteQueryBuilder localQueryBuilder = new SQLiteQueryBuilder();

                String typeDiscriminatorColumn = "_table";

                Set<String> cloudColumns = new HashSet<String>();
                cloudColumns.add(FileInfos.column(Table1._ID));
                cloudColumns.add(FileInfos.column(Table1.QUICK_KEY));
                cloudColumns.add(FileInfos.column(Table1.MIME_TYPE));
                cloudColumns.add(FileInfos.column(Table1.HASH));

                cloudQueryBuilder.setTables(Table1);
                String cloudTableQuery = cloudQueryBuilder.buildUnionSubQuery(typeDiscriminatorColumn, projection, cloudColumns, 0, Table1, selection, null, null);

使用该代码,这是我在记录查询语句时得到的结果:

SELECT quickkey, NULL AS _id, NULL AS hash, NULL AS created, NULL AS mimetype, NULL AS _id, NULL AS _mimetype, NULL AS _path FROM Table1

我尝试过的一些其他示例最终会得到相同的结果,其中几乎所有的表列都是“NULL AS”

但我的目标是让查询语句(对于UNION查询中的每个SELECT语句)匹配我手动编写的union语句。

列顺序无关紧要。

感谢任何帮助。

修改

我知道buildUnionQueries()用于添加多个SELECT语句,但问题是SELECT语句没有像我期望的那样被创建(这意味着我正在使用buildUnionSubquery()方法,这是什么我正在寻求帮助)

修改

以下代码大部分都有效,除了排序似乎不起作用:

SQLiteQueryBuilder cloudQueryBuilder = new SQLiteQueryBuilder();
SQLiteQueryBuilder localQueryBuilder = new SQLiteQueryBuilder();

String typeDiscriminatorColumn = "type";

                String[] cloudUnionColumns = {
                        FileInfos._ID,
                        FileInfos.QUICK_KEY,
                        FileInfos.MIME_TYPE,
                        FileInfos.CREATED,
                        FileInfos.HASH,
                        LocalItems.PATH,
                };

                Set<String> cloudColumns = new HashSet<String>();
                cloudColumns.add(FileInfos._ID);
                cloudColumns.add(FileInfos.QUICK_KEY);
                cloudColumns.add(FileInfos.MIME_TYPE);
                cloudColumns.add(FileInfos.HASH);
                cloudColumns.add(FileInfos.CREATED);

                cloudQueryBuilder.setTables(Tables.FILE_INFOS);
                String cloudTableQuery = cloudQueryBuilder.buildUnionSubQuery(typeDiscriminatorColumn, cloudUnionColumns, cloudColumns, 0, "cloud", selection, null, null);

                String[] localUnionColumns = {
                        LocalItems._ID,
                        FileInfos.QUICK_KEY,
                        LocalItems.MIME_TYPE,
                        LocalItems.CREATED,
                        FileInfos.HASH,
                        LocalItems.PATH,
                };
                Set<String> localColumns = new HashSet<String>();
                localColumns.add(LocalItems._ID);
                localColumns.add(LocalItems.PATH);
                localColumns.add(LocalItems.MIME_TYPE);
                localColumns.add(LocalItems.CREATED);

                localQueryBuilder.setTables(Tables.LOCAL_ITEMS);
                String localTableQuery = localQueryBuilder.buildUnionSubQuery(typeDiscriminatorColumn, localUnionColumns, localColumns, 0, "local", selection, null, null);

                Log.i(TAG, "cloud sub query - " + cloudTableQuery);
                Log.i(TAG, "local sub query - " + localTableQuery);

                String[] subQueries = {
                        cloudTableQuery,
                        localTableQuery,
                };
                sortOrder = "created DESC";
                String unionQuery = cloudQueryBuilder.buildUnionQuery(subQueries, sortOrder, null);
                Log.i(TAG, "query - " + unionQuery);

                return db.rawQuery(unionQuery, null);

我回来的示例行:

[_id: 33][quickkey: null][mimetype: image/jpeg][created: 1413327563000][hash: null][_path: /storage/emulated/0/WhatsApp/Media/WhatsApp Images/IMG-20141014-WA0001.jpg]

[_id: 47][quickkey: null][mimetype: image/jpeg][created: 1415751020000][hash: null][_path: /storage/emulated/0/Download/dota_2___clockwerk_by_sheron1030-d855txk.jpg]

我知道这些行是本地项目,因为quickkey = null且hash = null

[_id: 181][quickkey: 88hcvu3t3y832p4][mimetype: image/gif][created: 1414021932000][hash: 86a15752bb550259d89e184bb5930306a9f3c8b390837b6f9b387816b6dcd461][_path: null]

[_id: 257][quickkey: 57b35uy9f12a462][mimetype: image/png][created: 1410831493000][hash: 3ad838b6a5543760b588655ad9a1714c19ecb1b91a326a21282596b2fb650c48][_path: null]

我知道这些行是云项,因为path = null

虽然排序不起作用,并且列名没有别名(我也不知道如何),因为我希望对“已创建”列进行排序,但它们不会对整个结果集进行排序。而是分别为每个语句进行排序。

1 个答案:

答案 0 :(得分:2)

该方法似乎不支持x AS y。至少不是你需要的方式。

typeDiscriminator{Column|Value}

这些参数允许您在结果中包含一个列,以便您区分行所在的联合子查询:

SELECT
   'one' AS sourceTable
   ...
   FROM table1
UNION SELECT
   'two' AS sourceTable
  ...
  FROM table2

其中

  • typeDiscriminatorColumn"sourceTable"
  • typeDiscriminatorValue在第一个unionSubQuery中为"one",在第二个
  • 中为"two"
  • unionColumns两者都是常量,必须包含"sourceTable"

unionColumns vs columnsPresentInTable

unionColumns或多或少是最终projection。但是,列会被修改,最重要的是取决于columnsPresentInTable。但它所做的只是保持不变,或者如果该列不存在则用"NULL AS " + unionColumnEntry替换它。这允许您对具有完全相同列名的表执行联合查询:

SELECT
   column1,
   column2,
   NULL AS column3
   ...
UNION SELECT
   NULL AS column1,
   column2,
   column3,
   ...

具有以下内容:

  • unionColumns{ "column1", "column2", "column3" }
  • columnsPresentInTable在第一个子查询中为{ "column1", "column2" },在第二个子查询中为{ "column2", "column3" }
在您的情况下,

NULL AS <whatever>是因为您根本没有相同的列名。遗憾的是,通过AS进行映射并非此方法的意图。


您可以做的是在手动处理NULLAS部分时使用略微手动的#buildQuery方法

String[] projectionIn = {
   Table1._ID + " AS _id",
   ...
   "NULL as _path_to_file"
}
cloudQueryBuilder.buildQuery(projectionIn, null, null, ...);

或者你自己写了一个类似的方法来实际做你想要的。

参考文献: