2009-09-10 69 views
1

我有這個releases表在sqlite3的數據庫,列出一個應用程序的每個發行版本:加入有限的子查詢?

|release_id|release_date|app_id| 
|==========|============|======| 
|  1001| 2009-01-01 |  1| 
|  1003| 2009-01-01 |  1| 
|  1004| 2009-02-02 |  2| 
|  1005| 2009-01-15 |  1| 

所以每個APP_ID,將有多個行。我還有一個表,apps

|app_id|name | 
|======|========| 
|  1|Everest | 
|  2|Fuji | 

我想要顯示的應用程序的名稱和最新版本,其中「最新」指(a)最新的上映時間,如果有重複的,(B)最高RELEASE_ID 。

我可以爲單個應用程序做到這一點:

SELECT apps.name,releases.release_id,releases.release_date 
    FROM apps 
    INNER JOIN releases 
    ON apps.app_id = releases.app_id 
    WHERE releases.release_id = 1003 
    ORDER BY releases.release_date,releases.release_id 
    LIMIT 1 

當然ORDER BY適用於整個SELECT查詢,如果我離開了的WHERE子句,它仍然只返回一行。

這是一個小型數據庫的一次性查詢,所以緩慢的查詢,臨時表等都很好 - 我只是無法讓我的大腦圍繞SQL方式來做到這一點。

回答

1

這是很容易與解析函數ROW_NUMBER(),這是我猜的sqlite3不支持這樣做。但你可以做到這一點的方式,是一個有點比什麼在以前的答案給出更靈活:

SELECT 
    apps.name, 
    releases.release_id, 
    releases.release_date 
FROM apps INNER JOIN releases 
ON apps.app_id = releases.app_id 
WHERE NOT EXISTS (
-- // where there doesn't exist a more recent release for the same app 
    SELECT * FROM releases AS R 
    WHERE R.app_id = apps.app_id 
    AND R.release_data > releases.release_data 
) 

舉例來說,如果你有這樣的定義多個排序列「最新的」 MAX不會爲你工作,但是您可以修改EXISTS子查詢來捕捉「最新」的更復雜的含義。

+0

我喜歡它,而且我甚至明白它 - 謝謝! – 2009-09-10 19:31:38

0

這是醜陋的,但我認爲它會工作

select apps.name, (select releases.release_id from releases where releases.app_id=apps.app_id order by releases.release_date, releases.release_id), (select releases.release_date from releases where releases.app_id=apps.app_id order by releases.release_date, releases.release_id) from apps order by apps.app_id 

我希望有一些方法在一個嵌入式選擇讓這兩個列,但我不知道它。

0

嘗試:

SELECT a.name, 
     t.max_release_id, 
     t.max_date 
    FROM APPS a 
    JOIN (SELECT t.app_id, 
       MAX(t.release_id) 'max_release_id', 
       t.max_date 
      FROM (SELECT r.app_id, 
         r.release_id, 
         MAX(r.release_date) 'max_date' 
        FROM RELEASES r 
       GROUP BY r.app_id, r.release_id) 
     GROUP BY t.app_id, t.max_date) t 
1

這是「每組最大的N」問題。它每週在StackOverflow上出現好幾次。

我通常使用像在@Steve卡斯answer一個解決方案,但我這樣做是沒有子查詢(我與MySQL 4.0,它不支持子查詢鑽進習慣年前):

SELECT a.name, r1.release_id, r1.release_date 
FROM apps a 
INNER JOIN releases r1 
LEFT OUTER JOIN releases r2 ON (r1.app_id = r2.app_id 
    AND (r1.release_date < r2.release_date 
    OR r1.release_date = r2.release_date AND r1.release_id < r2.release_id)) 
WHERE r2.release_id IS NULL; 

在內部,這可能與NOT EXISTS語法的優化方式相同。您可以使用EXPLAIN來分析查詢以確定。


回覆您的評論,你可以只跳過測試release_date因爲release_id只是建立發佈的時間順序是有用的,而且我認爲它是保證是獨一無二的,所以這簡化了查詢:

SELECT a.name, r1.release_id, r1.release_date 
FROM apps a 
INNER JOIN releases r1 
LEFT OUTER JOIN releases r2 ON (r1.app_id = r2.app_id 
    AND r1.release_id < r2.release_id) 
WHERE r2.release_id IS NULL; 
+0

原來,一些「發佈日期」是NULL,這不像那些...但這是最接近我的心理表示,所以它會幫助我瞭解這些各種查詢如何映射到對方。謝謝! – 2009-09-10 17:43:40

0

Err第二次嘗試。假設ID是單調遞增的,並且溢出不是可能發生的,您可以忽略日期並且只是這樣做:

SELECT apps.name, releases.release_id, releases.release_date 
FROM apps INNER JOIN releases on apps.app_id = releases.app_id 
WHERE releases.release_id IN 
(SELECT Max(release_id) FROM releases 
GROUP BY app_id);