2012-02-10 63 views
1

我有以下的數據庫結構:複雜的MySQL數據庫查詢

站點表

id | name | other_fields 

備份表

id | site_id | initiated_on(unix timestamp) | size(float) | status 

所以Backups表有一個與多對一的關係Sites表通過連接


而且我想輸出的格式如下

name | Latest initiated_on | status of the latest initiated_on row 

的數據和我有以下SQL查詢

SELECT *, `sites`.`id` as sid, SUM(`backups`.`size`) AS size 
FROM (`sites`) 
LEFT JOIN `backups` ON `sites`.`id` = `backups`.`site_id` 
WHERE `sites`.`id` = '1' 
GROUP BY `sites`.`id` 
ORDER BY `backups`.`initiated_on` desc 

的事情是,上述查詢我可以實現我在尋找的東西,但唯一的問題是我沒有得到最新的initiated_on值。

所以,如果我在backups有3行與site_id = 1,查詢不initiated_on挑選出具有最高值的行。它只是挑出任何一行。

請幫幫忙,並

在此先感謝。

+1

當你有一個GROUP BY時,你不應該編寫SELECT * - 你將返回的值將是任意的。在大多數DB中,這甚至不是有效的SQL語句。 (即使你不使用GRUOP BY,SELECT *仍然被認爲是一種不好的做法)。 – 2012-02-10 14:55:30

+0

我可以將它更改爲'SELECT sites。*'? – ekhaled 2012-02-10 15:00:14

+0

你還沒有在你的SELECT中加入initiate_on,這可能是爲什麼它沒有返回它。 – CBusBus 2012-02-10 15:26:57

回答

2

你應該嘗試:

SELECT sites.name, FROM_UNIXTIME(b.latest) as latest, b.size, b.status 
FROM sites 
LEFT JOIN 
    (SELECT bg.site_id, bg.latest, bg.sizesum AS size, bu.status 
    FROM 
     (SELECT site_id, MAX(initiated_on) as latest, SUM(size) as sizesum 
     FROM backups 
     GROUP BY site_id) bg 
    JOIN backups bu 
    ON bu.initiated_on = bg.latest AND bu.site_id = bg.site_id 
) b 
ON sites.id = b.site_id 
  1. GROUP BY子查詢 - bg在這裏,你可以使用SELECT列只有那些要麼列通過函數聚合或列在GROUP BY部分。

    http://dev.mysql.com/doc/refman/5.5/en/group-by-hidden-columns.html

  2. 一旦你擁有所有你需要重新加入的結果backups找到其他值與最新時間戳的行聚合值 - b

  3. 最後將結果連接到sites表以獲取名稱 - 如果要列出所有網站,即使沒有備份,也要將其加入。

+0

這是最有效的解決方案,但您還應該將「bu.site_id = bg.site_id」添加到最裏面的連接 – nnichols 2012-02-10 16:36:45

+0

是的你是對的,我假設爲int時間戳記足夠獨特,已編輯。 – piotrm 2012-02-10 16:43:50

+0

謝謝,很好的解釋和查詢在我粗略的基準測試中是高效的。 – ekhaled 2012-02-12 16:57:10

1

嘗試這樣的:

select S.name, B.initiated_on, B.status 
from sites as S left join backups as B on S.id = B.site_id 
where B.initiated_on = 
     (select max(initiated_on) 
      from backups 
      where site_id = S.id) 
1

要獲取最新的時候,你需要做一個子查詢是這樣的:

SELECT sites.id as sid, 
      SUM(backups.size) AS size 
      latest.time AS latesttime 
     FROM sites AS sites 
LEFT JOIN (SELECT site_id, 
        MAX(initiated_on) AS time 
       FROM backups 
      GROUP BY site_id) AS latest 
     ON latest.site_id = sites.id 
LEFT JOIN backups 
     ON sites.id = backups.site_id 
    WHERE sites.id = 1 
    GROUP BY sites.id 
    ORDER BY backups.initiated_on desc 

我已刪除了SELECT *,因爲這隻會使用MySQL工作,一般是不好的做法呢。如果包含其他字段(即使是單獨的),非MySQL RDBS將引發錯誤,並且您需要將此查詢本身放入子查詢中,然後對網站表執行INNER JOIN以獲取其餘字段。這是因爲他們將嘗試將所有這些添加到GROUP BY語句中,如果您有長文本字段,則會失敗(或者至少非常慢)。

+0

差不多.....不得不在子查詢中做'GROUP BY site_id' ... – ekhaled 2012-02-10 17:12:04

+0

糟糕!這是我的想法。編輯爲使用正確的列名稱。 – 2012-02-10 17:41:31