2012-02-10 11 views
1

は、私は、次のデータベース構造を持っていますテーブルは経由で接続されています複雑MySQLのデータベースクエリ


この事は、私は上記のクエリで、ある私は、次のフォーマットで出力データを

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値を取得しないことです。

私は= 1site_idbackupsに3行を持っていたのであれば、クエリはinitiated_onで最も高い値を持つ行を選び出すことはありません。それはちょうど行を選びます。事前に

助けてください、と

感謝。

+1

GROUP BYを使用しているときにSELECT *を記述しないでください。返される値は任意です。ほとんどのDBでは、これは有効なSQL文ではありません。 (GRUOP BYを使用していなくても、SELECT *はやはり悪い習慣とみなされます)。 –

+0

「SELECT sites。*」に変更することはできますか? – ekhaled

+0

あなたはそれが返されていないと思われる、あなたのSELECTにiniti_onを追加していません。 – CBusBus

答えて

2

あなたが試してみてください:GROUP BYサブクエリで

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. を - ここbg、あなたがSELECTに使用できる唯一の列のいずれかである列です機能によって集約されるか、またはGROUP BY部分にリストされます。 b -

  2. あなたは、最新のタイムスタンプを持つ行の他の値を見つけるためにbackupsに再び結果を結合するために必要なすべての集計値を持っていたら

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

  3. 最後に結果をsitesテーブルに結合して名前を取得するか、バックアップなしですべてのサイトを一覧表示する場合は結合を残します。

+0

これは最も効率的な解決方法ですが、さらに内側の結合に「bu.site_id = bg.site_id」を追加することもできます – nnichols

+0

はい、タイムスタンプは十分にユニークで編集されていました。 – piotrm

+0

ありがとう、よく説明されており、クエリは私の原油ベンチマークで効率的です。 – ekhaled

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 

これが唯一のMySQLを使用して動作し、とにかく一般的に悪い習慣であるだろうと私はSELECT *を削除しました。個別の場合でも他のフィールドを含めると、MySQL以外のRDBSはエラーをスローします。このクエリ自体をサブクエリにしてから、サイトテーブルのINNER JOINを実行して残りのフィールドを取得する必要があります。これは、それらがすべてGROUP BYステートメントに追加しようとしているためです。長いテキストフィールドがある場合、これは失敗します(または少なくとも非常に遅いです)。

+0

ほとんど.....サブクエリでGROUP BY site_idを実行する必要がありました... – ekhaled

+0

おっと!それが私の心にあったものでした。右の列名を使用するように編集されました。 –