2015-02-09 71 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

我最終選擇了與我編輯中類似的連接,因爲它們工作得非常好,並且還可以一次性收集其他信息。