mysql查询使用聚合函数来选择字段值

时间:2013-01-14 21:59:08

标签: mysql aggregate

MySQL 5.5.29 这是我正在处理的mysql查询但没有成功:

SELECT ID, Bike, 
(SELECT IF( MIN( ABS( DATEDIFF(  '2011-1-1', Reading_Date ) ) ) = ABS( DATEDIFF(  '2011-1-1', Reading_Date ) ) , Reading_Date, NULL ) FROM odometer WHERE Bike=10  ) AS StartDate, 
(SELECT IF( MIN( ABS( DATEDIFF(  '2011-1-1', Reading_Date ) ) ) = ABS( DATEDIFF(  '2011-1-1', Reading_Date ) ) , Miles, NULL ) FROM odometer WHERE Bike=10  ) AS BeginMiles, 
(SELECT IF( MIN( ABS( DATEDIFF(  '2012-1-1', Reading_Date ) ) ) = ABS( DATEDIFF(  '2012-1-1', Reading_Date ) ) , Reading_Date, NULL ) FROM odometer  WHERE Bike=10  ) AS EndDate,
(SELECT IF( MIN( ABS( DATEDIFF(  '2012-1-1', Reading_Date ) ) ) = ABS( DATEDIFF(  '2012-1-1', Reading_Date ) ) , Miles, NULL ) FROM odometer WHERE Bike=10  ) AS EndMiles
FROM  `odometer` 
WHERE Bike =10;

结果是:

ID  Bike    StartDate   BeginMiles  EndDate EndMiles
14  10 [->] 2011-04-15  27.0    NULL    NULL
15  10 [->] 2011-04-15  27.0    NULL    NULL
16  10 [->] 2011-04-15  27.0    NULL    NULL

摩托车车主每年1月1日或附近进入一次里程表读数。我想用摩托车计算总里程数。

表格里程表中的数据如下所示: http://bmwmcindy.org/so/Grid011.png

因此,为了计算2011年这辆自行车的里程数,我需要确定哪些记录更接近2011年1月1日,那就是记录14.起始里程为27.我需要找到最接近的记录2012年1月1日,即创纪录的15. 2011年的终止里程为10657(这也将是计算2012年时的起始里程表读数。

这是表格:

DROP TABLE IF EXISTS `odometer`;
CREATE TABLE IF NOT EXISTS `odometer` (
  `ID` int(3) NOT NULL AUTO_INCREMENT,
  `Bike` int(3) NOT NULL,
  `is_MOA` tinyint(1) NOT NULL,
  `Reading_Date` date NOT NULL,
  `Miles` decimal(8,1) NOT NULL,
  PRIMARY KEY (`ID`),
  KEY `Bike` (`Bike`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=22 ;

odometer的数据

INSERT INTO `odometer` (`ID`, `Bike`, `is_MOA`, `Reading_Date`, `Miles`) VALUES
(1, 1, 0, '2012-01-01', 5999.0),
(2, 6, 0, '2013-02-01', 14000.0),
(3, 7, 0, '2013-03-01', 53000.2),
(6, 1, 1, '2012-04-30', 10001.0),
(7, 1, 0, '2013-01-04', 31000.0),
(14, 10, 0, '2011-04-15', 27.0),
(15, 10, 0, '2011-12-31', 10657.0),
(16, 10, 0, '2012-12-31', 20731.0),
(19, 1, 1, '2012-09-30', 20000.0),
(20, 6, 0, '2011-12-31', 7000.0),
(21, 7, 0, '2012-01-03', 23000.0);

我正在尝试从不同的记录中获取日期和里程,以便我可以从结束里程中获取起始里程,以获得特定年份(在示例中为Bike = 10)的特定年份的总里程(在这种情况下) 2011年)。

我已经阅读了很多关于聚合函数和从正确记录中获取值的问题。我认为答案是以某种方式在子查询中。但是当尝试上面的查询时,我只从第一条记录中获取数据。在这种情况下,结束里程应来自第二条记录。

我希望有人能指出我正确的方向。

1 个答案:

答案 0 :(得分:0)

迈尔斯应该稳步增长。如果像这样的东西工作会很好:

select year(Reading_Date) as yr,
        max(miles) - min(miles) as MilesInYear
from odometer o
where bike = 10
group by year(reading_date)
唉,你的逻辑确实比你想象的要困难得多。对于具有leadlag函数的SQL Server 2012或Oracle等数据库,这将更容易。

我的方法是找到每年的第一个和最后一个阅读日期。您可以使用相关子查询来计算:

select o.*,
       (select max(date) from odometer o2 where o.bike = o2.bike and o2.date <= o.date - dayofyear(o.date) + 1
       ) ReadDateForYear
from odometer o

接下来,总结一下自行车和年级。如果第一年或年初没有读取日期,请使用第一个日期:

select bike, year(date) as yr,
       coalesce(min(ReadDateForYear), min(date)) as FirstReadDate,
       coalesce(min(ReadDateForNextYear), max(date)) as LastReadDate
from (select o.*,
             (select max(date) from odometer o2 where o.bike = o2.bike and o2.date <= o.date - dayofyear(o.date) + 1
             ) ReadDateForYear,
             (select max(date) from odometer o2 where o.bike = o2.bike and o2.date <= date_add(o.date -      dayofyear(0.date) + 1 + interval 1 year)
             ) ReadDateForNextYear
      from odometer o
     ) o
group by bike, year(date)

我来称呼这个。要获得最终结果,您需要以下内容:

select the fields you need
from <q> q join
     odometer s
     on s.bike = q.bike and year(s.date) = q.year join
     odometer e
     on s.bike = q.bike and year(e.date) = q.year

注意:此SQL未经测试。我确定存在语法错误。