2017-02-12 55 views
1

以下查询导致错误。派生表查询不能在mysql中工作

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 
+0

它看起来像一个颇为曲折的查询BTW – Strawberry

+0

你能解释一下吗?间接地, – DesirePRG

+0

。见http://meta.stackoverflow.com/questions/333952/why-should-i-provide-an-mcve-for-what-seems-to-me-to-be-a-very-simple-sql-query – Strawberry

回答

3

您最后还有一个额外的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

你应该这样做。如下:

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; 
1

您简化查询和像这样的东西删除加入伪表:不必更新查询

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` 
+0

得到这个错误错误1054(42S22):'字段列表'中的未知列'm.monend' – DesirePRG

+0

我设法修复错误,您的查询似乎是正确的。非常感谢 – DesirePRG

+0

对不起。我忘了删除表别名。我已经更新了代码示例。 –