复杂的MySQL数据库查询

时间:2012-02-10 14:53:07

标签: php mysql

我有以下数据库结构:

网站表

id  |  name  |  other_fields

备份表

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

所以Backups表格与Sites表之间存在多对一关系site_id


我想以下列格式输出数据

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中有site_id = 1的3行,则查询不会选择initiated_on中值最高的行。它只是挑出任何一行。

请帮忙,

提前感谢。

3 个答案:

答案 0 :(得分: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的唯一列是由函数聚合或列在{{1}中的列部分。

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

  2. 获得所有汇总值后,您需要再次将结果加入GROUP BY,以查找具有最新时间戳的行的其他值 - backups

  3. 最后将结果加入b表以获取名称 - 如果要列出所有网站,即使没有备份,也可以离开加入。

答案 1 :(得分: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)

答案 2 :(得分: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会抛出错误,甚至是单独的,您需要将此查询本身放入子查询中,然后对sites表执行INNER JOIN以获取其余字段。这是因为他们将尝试将所有这些添加到GROUP BY语句中,如果您有长文本字段,则会失败(或者至少非常慢)。