2015-02-09 107 views
0

我正在使用sqlite3,但它的SQL支持是相当标准的,所以只要SQL不包含任何专有扩展,所有应该都是好的。我的架构如下:查询优化,摆脱子查询

create table test (
    _id integer primary key, 
    name text, 
    enabled integer not null default 1 
); 
create table task (
    _id integer primary key, 
    _test_id integer not null references test on delete cascade, 
    favorite integer not null default 0, 
    comment text 
); 

简而言之:有可以启用或不测试;测试有多个任务,可以是最喜欢的,并且可以有评论。

两个最复杂的查询,我需要编写如下:

  • 一个选择它检索信息的数据库是否包含至少1喜爱和至少1评论任务对于任何测试启用(即唐试验组)。我想出了以下的怪物:

    select 
        exists(select task._id from task as task inner join test as test on task._test_id=test._id where task.favorite=1 and test.enabled=1 limit 1) as has_favorite, 
        exists(select task._id from task as task inner join test as test on task._test_id=test._id where task.comment is not null and test.enabled=1 limit 1) as has_commented; 
    
  • 一个选择符合有关其任务计数信息一起取回试验核心数据(ID,姓名等),测试是否包含至少1喜爱和至少1评论任务。我想出了这个:

    select 
        test.*, 
        (select count(*) from task where _test_id=test._id) as task_count, 
        exists(select _id from task where favorite=1 and _test_id=test._id limit 1) as has_favorite, 
        exists(select _id from task where comment is not null and _test_id=test._id limit 1) as has_commented 
    from test as test where test.enabled=1 order by test._id asc 
    

其实,“has_favorite”和“has_commented”信息不是唯一的,但他们描绘了我的怀疑 - 这些查询都是相当大的,含有相当数量的子查询(我读取子查询对性能不利)和重复。

问题:是否可以更容易地编写查询?让他们更好,更简洁?不是很重复?例如,我想也许有办法只执行任务和测试表之间的一个连接,并以某种方式从那里派生数据。

编辑:所以看来我可以这样写的第一个:

select 
     count(*) as task_count, 
     max(task.favorite) as has_favorite, 
     count(task.comment) as has_commented 
    from task as task inner join test as test on task._test_id=test._id where test.enabled=1; 

这对于第二个:

select 
    test.*, 
    count(*) as task_count, 
    max(task.favorite) as has_favorite, 
    count(task.comment) as has_commented 
from task as task inner join test as test on task._test_id=test._id where test.enabled=1 group by test._id; 

如果MAX(task.favorite)是什么> 0表示至少有1个任务是最喜欢的。我可以用'sum(task.favorite)'代替它,如果总和> 0,那么有一个最喜欢的。

这是否比原来的建议好(存在(子选择))?这似乎更容易。

+0

是否有版本3.8.3或更高版本(它具有公用表表达式)? – 2015-02-09 22:03:08

+0

我应该在3.8.4.3(Android Lollipop,5.0)上运行,但我可能必须早于3.7.4(Android 4.0)兼容。不过,我会好奇的,你会采取什么。 – wujek 2015-02-09 22:13:03

+0

[WITH子句](http://www.sqlite.org/lang_with.html)。你可以创建一个视图。 – 2015-02-10 07:47:46

回答

0

我最终选择了与我编辑中类似的连接,因为它们工作得非常好,并且还可以一次性收集其他信息。