派生表查询无法在mysql中运行

时间:2017-02-12 06:36:46

标签: mysql database

以下查询会导致错误。

select monstart,
       sum(datediff(least(m.monend, t.end_date) + interval 1 day,
                    greatest(m.monstart, t.start_date)
                   )
           ) as days_worked
from travel t join
     (select date('2016-01-01') as monstart, date('2016-01-31') as monend union all
      select date('2016-02-01') as monstart, date('2016-02-29') as monend union all
 select date('2016-03-01') as monstart, date('2016-03-31') as monend union all
 select date('2016-04-01') as monstart, date('2016-04-30') as monend union all
 select date('2016-05-01') as monstart, date('2016-05-31') as monend union all
 select date('2016-06-01') as monstart, date('2016-06-30') as monend union all
 select date('2016-07-01') as monstart, date('2016-07-31') as monend union all
 select date('2016-08-01') as monstart, date('2016-08-31') as monend union all
 select date('2016-09-01') as monstart, date('2016-09-30') as monend union all
 select date('2016-10-01') as monstart, date('2016-10-31') as monend union all
 select date('2016-11-01') as monstart, date('2016-11-30') as monend union all
 select date('2016-12-01') as monstart, date('2016-12-31') as monend union all
     ) m
     on t.end_date >= m.monstart and t.start_date <= m.monend
group by m.monstart;

错误如下。

ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ') m
     on t.end_date >= m.monstart and t.start_date <= m.monend
group by m.mon' at line 19

3 个答案:

答案 0 :(得分:2)

最后你还有一个额外的union all。只需删除它。

select monstart,
       sum(datediff(least(m.monend, t.end_date) + interval 1 day,
                    greatest(m.monstart, t.start_date)
                   )
           ) as days_worked
from travel t join
     (select date('2016-01-01') as monstart, date('2016-01-31') as monend union all
      select date('2016-02-01') as monstart, date('2016-02-29') as monend union all
 select date('2016-03-01') as monstart, date('2016-03-31') as monend union all
 select date('2016-04-01') as monstart, date('2016-04-30') as monend union all
 select date('2016-05-01') as monstart, date('2016-05-31') as monend union all
 select date('2016-06-01') as monstart, date('2016-06-30') as monend union all
 select date('2016-07-01') as monstart, date('2016-07-31') as monend union all
 select date('2016-08-01') as monstart, date('2016-08-31') as monend union all
 select date('2016-09-01') as monstart, date('2016-09-30') as monend union all
 select date('2016-10-01') as monstart, date('2016-10-31') as monend union all
 select date('2016-11-01') as monstart, date('2016-11-30') as monend union all
 select date('2016-12-01') as monstart, date('2016-12-31') as monend -- removed a union all from here
     ) m
     on t.end_date >= m.monstart and t.start_date <= m.monend
group by m.monstart;

答案 1 :(得分:1)

你应该这样做。如下:

  select monstart,
           sum(datediff(least(m.monend, t.end_date) + interval 1 day,
                        greatest(m.monstart, t.start_date)
                       )
               ) as days_worked
    from travel t join
         (select date('2016-01-01') as monstart, date('2016-01-31') as monend union all
          select date('2016-02-01') as monstart, date('2016-02-29') as monend union all
     select date('2016-03-01') as monstart, date('2016-03-31') as monend union all
     select date('2016-04-01') as monstart, date('2016-04-30') as monend union all
     select date('2016-05-01') as monstart, date('2016-05-31') as monend union all
     select date('2016-06-01') as monstart, date('2016-06-30') as monend union all
     select date('2016-07-01') as monstart, date('2016-07-31') as monend union all
     select date('2016-08-01') as monstart, date('2016-08-31') as monend union all
     select date('2016-09-01') as monstart, date('2016-09-30') as monend union all
     select date('2016-10-01') as monstart, date('2016-10-31') as monend union all
     select date('2016-11-01') as monstart, date('2016-11-30') as monend union all
     select date('2016-12-01') as monstart, date('2016-12-31') as monend 
         ) m
         on t.end_date >= m.monstart and t.start_date <= m.monend
    group by m.monstart;

答案 2 :(得分:1)

您可以使用以下内容简化查询并删除join伪表:

select 
    sum(datediff(least(monend, end_date) + interval 1 day,greatest(monstart, start_date))) as `days_worked`,
    (adddate(last_day(start_date), 1) - interval 1 month) as `monstart`,
    last_day(start_date) as `monend`
from travel
group by `monstart`,`monend`

这可以在任何一年使用而无需更新您的查询。

编辑 - 请改为尝试:

select 
    (adddate(last_day(start_date), 1) - interval 1 month) as `monstart`,
    last_day(start_date) as `monend`,
    sum(
        datediff(
            least(last_day(start_date), end_date) + interval 1 day,
            greatest((adddate(last_day(start_date), 1) - interval 1 month), start_date))
    ) as `days_worked`
from travel
group by `monstart`,`monend`