SQL查询返回超出范围内允许量的记录

时间:2019-05-13 16:44:04

标签: mysql sql join group-by count

想象一下,允许一个工人在定义的时间段内有可变数量的轮班。我们要查询任何期间内超出允许金额的班次以及所有期间以外的班次。

我已经将db-fiddle与测试查询链接了。这里的问题是:

  1. 对于多余的班次,合并班次的顺序是不确定的。我只希望看到多余的班次(2016-05-30是仅授权3个班次的第四班次。)
  2. 我还希望看到尚未得到授权的3个班次(2019-04-25、2019-06-02、2019-06-04)。

我希望我需要翻转查询(即从Shift join Authorization中选择),并使用group by,order by和limit的某种组合,但是我没有取得任何成功。任何输入将不胜感激。

search = (text$: Observable<string>) =>
  text$.pipe(
    // use this.param1 and this.param2 here 
  );

CREATE TABLE `Authorization` (
  `AuthorizationId` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `WorkerId` int(10) unsigned NOT NULL,
  `Start` date NOT NULL,
  `End` date NOT NULL,
  `ShiftsAllowed` int(10) unsigned NOT NULL,
  PRIMARY KEY (`AuthorizationId`)
);

CREATE TABLE `Shift` (
  `ShiftId` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `WorkerId` int(10) unsigned NOT NULL,
  `Date_` date NOT NULL,
  PRIMARY KEY (`ShiftId`)
);

INSERT INTO Authorization (WorkerId,Start,End,ShiftsAllowed) VALUES 
(1,'2019-05-01','2019-05-15',2),
(1,'2019-05-16','2019-05-31',3);

INSERT INTO Shift (WorkerId,Date_) VALUES 
(1,'2019-04-25'),
(1,'2019-05-01'),
(1,'2019-05-10'),
(1,'2019-05-16'),
(1,'2019-05-20'),
(1,'2019-05-25'),
(1,'2019-05-30'),
(1,'2019-06-02'),
(1,'2019-06-04');

View on db-fiddle

2 个答案:

答案 0 :(得分:0)

由于MySQL 5.7不支持窗口功能。

我用相关子查询代替了它。

尝试一下:

select a3.shiftid, a3.workerid, a3.date_ from (
select a2.*, 
(select count(*) 
 from (select s.*, a.start, a.end, a.shiftsallowed
        from Shift s
        left join Authorization a
        on a.workerid = s.workerid
        and s.date_ between a.start and a.end) a1 
        where a1.date_ <= a2.date_ 
        and a1.workerid = a2.workerid and a1.start = a2.start and a1.end  = a2.end) rnk
from (
select s.*, a.start, a.end, a.shiftsallowed
from Shift s
left join Authorization a
on a.workerid = s.workerid
and s.date_ between a.start and a.end )a2)a3
where a3.rnk > a3.shiftsallowed or rnk = 0

如果您不了解答案,建议您运行此查询。

select s.*, a.start, a.end, a.shiftsallowed
from Shift s
left join Authorization a
on a.workerid = s.workerid
and s.date_ between a.start and a.end 

然后添加等级列-相关子查询

测试结果:

DB-Fiddle

答案 1 :(得分:0)

为提供MCVE做得很好。

对于8.0之前的版本...

SELECT workerid
     , date_   FROM 
     ( SELECT s.workerid
            , a.authorizationid
            , a.start
            , a.end
            , a.shiftsallowed
            , s.date_
            , CASE WHEN @prev = authorizationid THEN @i:=@i+1 ELSE @i:=1 END i
            , @prev:=authorizationid prev 
         FROM shift s 
         LEFT
         JOIN authorization a 
           ON a.workerid = s.workerid 
          AND s.date_ BETWEEN a.start AND a.end 
         JOIN 
            ( SELECT @prev:=null,@i:=0 ) vars 
        ORDER 
           BY a.authorizationid
            , s.date_
     ) x  WHERE i>shiftsallowed OR authorizationid IS NULL;