我正在使用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
);
简而言之:有些测试可以启用或不启用;测试有多个任务,可以是最喜欢的,也可能有评论。
我需要编写的两个最复杂的查询如下:
一个select,用于检索数据库是否包含至少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;
一个select,它检索测试核心数据(id,name等)以及有关其任务计数的信息,测试是否包含至少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,有一个最爱。
这是否比原始提案(存在(subselect))更好?这似乎更容易。
答案 0 :(得分:0)
我最终加入了类似于我编辑中的连接,因为它们工作得非常好,也允许一次性收集其他信息。