android - 根据保存在另一个表中的关系从表中进行选择

标签 android sql sqlite

我的处境
我在android上使用sqlite来存储一些数据。这些数据都在同一个表中,但每一行可以与同一表中的其他行有一个或多个关系。这些关系保存在另一个表中。这样想:
在表1中,可以是id为0的行,该行有2个子级,id为1和2。这两个子项将再次保存在表1中,但在表2中,将为这些子项中的每个子项从id 0映射到它们自己的id。这些表可能如下所示:

+---------------------------+     
|           Table 1         |     
+------+------+------+------+     
|  ID  |   .... Data ....   |     
+------+------+------+------+     
|  0   | ...  | ...  | ...  |   <--- This would be the parent of rows 1 & 2         
|  1   | ...  | ...  | ...  |        as indicated in the other table
|  2   | ...  | ...  | ...  |      
|  3   | ...  | ...  | ...  |     

+----------------------------+
|           Table 2          | 
+-------------+--------------+
|  Parent ID  |   Child ID   |
|      0      |       1      |   <-- This means that row 0 has
|      0      |       2      |   <-- 2 children with the ids 1 and 2  
|      2      |       5      |          
|      3      |       2      |   <-- Each row can have multiple parents and/or children

我想做的基本上是从表1中选择带有一些任意where子句的where子句,如果这个where子句与行0匹配,我还需要选择行0的子代以及这些子代的子代等等。既然我通常不善于解释,让我再解释一遍:
如果我运行这样的select
SELECT * FROM TABLE1 WHERE ...

我会得到这样的结果:
+------+------+------+------+     
|  ID  |   .... Data ....   |     
+------+------+------+------+     
|  0   | ...  | ...  | ...  |      
|  3   | ...  | ...  | ...  |

但我想得到的是:
+------+---------+------+------+------+     
|  ID  | isChild |   .... Data ....   |     
+------+---------+------+------+------+     
|  0   |    0    | ...  | ...  | ...  |   <--- This row along with row 3 is what actually matches the where clause            
|  1   |    1    | ...  | ...  | ...  |
|  2   |    1    | ...  | ...  | ...  |      
|  5   |    2    | ...  | ...  | ...  |
|  3   |    0    | ...  | ...  | ...  |   <--- This row along with row 0 is what actually matches the where clause            
|  2   |    1    | ...  | ...  | ...  |
|  5   |    2    | ...  | ...  | ...  |

只有第1行和第3行与where子句实际匹配。子行的顺序并不重要,但它们应该紧跟在父行之后,“is child”列将用于指示行是否是子行以及它是什么子行。
注意上面输出中从顶部开始的第三行,即id为2的那一行。它在“is child”中有2,因为它是上面一行的子级,上面也是子级。您可以将上面的整个输出看作一棵树,如下所示:
- 0 
   - 1      <-- 1 is a child of 0
   - 2      <-- 2 is a child of 0
      - 5   <-- 5 is a child of 2
- 3
   - 2      <-- 2 is a child of 3
      - 5   <-- 5 is a child of 2

“ischild”列实际上告诉您您在树的哪个级别上。
问题
到目前为止,我已经用多个selects实现了这一点。我首先从table1中选择行,从每一行中获取id,然后从table2中为每一行选择映射。使用这些映射,我将从表1中选择子项,然后再次在表2中查找子项的映射,依此类推。不需要天才就能看出,这会很快导致巨大的性能问题,而且确实相当缓慢。
从那以后,我一直试图通过减少所需的selects数量来改进这一点,但现在我遇到了困难。我已经实现了我能想到的任何一种改进,它在大部分情况下都是有效的,但是如果你处理的是大数据集,一切都会以指数级速度减慢,我看不到任何其他方法可以在代码中改进这一点。我开始思考,并得出结论,如果我能以某种方式选择一切,在我上面所述的方式,它将为我解决一系列的问题。
到目前为止我试图解决这个问题
由于我无法在代码中进一步改进这一点,所以我将注意力转向了sql。我已经做了很多不相关的改进,通过实现触发器来完成最常见的任务,比如创建和删除表2中的映射,从而获得了巨大的性能提升。我一直希望我也能以类似的方式解决这个问题。
我试过各种各样的JOINs或UNIONs,但似乎没有什么能像我期望的那样工作。我有一种感觉,我可能走错了路。到目前为止,我还没有尝试将“ischild”列包括在内。
This is a link to the SQLFiddle I use to test my selects
当我开始研究这个问题时,我愚蠢地认为一个简单的JOIN就能解决问题,但我现在怀疑这一点,我也不确定我想做的事情是否可能(以一种有效的方式)。
这个问题让我意识到我对sql知之甚少,如果某个sql向导能来告诉我这个解决方案有多简单,我将非常感激!(尽管我怀疑我的问题的解决方法其实并没有那么简单)
请记住,这个问题是专门讨论android上的sqlite。但我试图使这个问题尽可能一般化,因为它也适用于许多其他sql实现或操作系统。
如果你对这个问题有一个非常好的答案,有一个简单的解决方案,让我很震惊,并且有一个很好的解释,那么我会毫不犹豫地赏赐你一笔。

最佳答案

要递归地读取子对象,必须使用recursive common table expression
然而,这是在sqlite 3.8.3中引入的,所以你的android设备不太可能支持它。
您必须继续使用多个查询,或者在ndk中使用自己的sqlite版本。

关于android - 根据保存在另一个表中的关系从表中进行选择,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25999883/

相关文章:

android - 创建带警报的重复服务

c# - SQL 将所有可为空的列转换为不可为空的列

c# - 带有 IN 子句的 SQL 到 LINQ

mysql - SQL 将两个表与第三个表连接起来

c# - Nuget 安装 System.Data.Sqlite 时出现脚本错误

android - 如何在 Retrofit-2.0+ android 中设置超时

android - 如何将 JSONArray 从 Activity 传递到 Html 脚本?

python - 使用来自多个表的随机行的 SELECT UNION 查询

database - SQLite和Firebase数据库之间的同步,用户离线数据存储在sqlite中,在线数据存储在firebase中

安卓工作室 : How to change default cursor style and behavior?