0

我遇到了一个有趣的问题。我有一张工人身份证和他们来访天数的表格。这是转储:

CREATE TABLE `pp` (
  `id` int(11) DEFAULT '1',
  `day` int(11) DEFAULT '1',
  `key` varchar(45) NOT NULL,
 PRIMARY KEY (`key`)
) 

INSERT INTO `pp` VALUES 
   (1,1,'1'),
   (1,20,'2'),
   (1,50,'3'),
   (1,70,'4'),
   (2,1,'5'),
   (2,120,'6'),
   (2,90,'7'),
   (1,90,'8'),
   (2,100,'9');

所以我需要找到至少一次旷工超过 50 天的工人。例如,如果工人在第 5 天、第 95 天、第 96 天、第 97 天访问,如果我们查看 deltas,我们可以看到最大的 delta (90) 超过 50,因此我们应该将这个工人包含在结果中。问题是我如何有效地找到不同工人访问之间的增量?

我什至无法想象如何使用 mysql 表作为结果数据数组。

所以我们需要为不同的工人分离天的价值,对它们进行排序,然后找到每个工人的最大增量。但是怎么做?例如,有什么方法可以在 sql 中枚举排序数组?

4

3 回答 3

2

试试这个查询 -

编辑:

SELECT t.id, t.day1, t.day2 FROM (
  SELECT p1.id, p1.day day1, p2.day day2 FROM pp p1
    JOIN (SELECT * FROM pp ORDER BY day) p2
      ON p1.id = p2.id AND p1.day < p2.day
   GROUP BY p1.id, p1.day
  )  t
GROUP BY t.id
HAVING MAX(day2 - day1) >= 50
于 2012-11-28T08:42:24.937 回答
1

这是我用来处理此类问题的一种方法:

SELECT distinct t3.id  FROM
(SELECT t1.id, t1.day, MIN(t2.day) nextday
FROM pp t1
JOIN pp t2 ON t1.id=t2.id AND t1.day<t2.day
GROUP BY t1.id, t1.day
HAVING nextday-t1.day >50) t3

编辑这个版本稍微好一点)这会找到所有 delta > 50 的 ID。(我假设这就是你所追求的)

要查看它的工作原理:SQL fiddle

要找到最大增量:

SELECT t3.id, MAX(t3.nextday-t3.day)  FROM
(SELECT t1.id, t1.day, MIN(t2.day) nextday
FROM pp t1
JOIN pp t2 ON t1.id=t2.id AND t1.day<t2.day
GROUP BY t1.id, t1.day) t3
GROUP BY t3.id

背后的逻辑是找到“下一个”项目,无论这意味着什么。由于这是一个有序属性,下一项可以定义为在那些值大于所检查值的行中具有最低值......然后将“下一个”值连接到原始值,计算增量,并仅返回适用的那些。如果您还需要其他列,只需在外部选择上对原始表执行 JOIN。

我不确定这是否是关于性能的最佳解决方案,但我只为一次性报告编写查询,我可以用它来让查询运行一段时间。

但是,可能会出现一个语义错误:如果有人在第 1、第 2 和第 3 天在场,但之后从未出现,则不会发现缺席。为了克服这个问题,您可以在表中添加一个特殊的行,其中包含UNION一个 select 指定所有 s 的明天计数的表ID,但这会使该查询令人作呕,以至于不尝试将其写下来......

于 2012-11-28T08:33:00.460 回答
1

这也可能是一个解决方案:

select distinct pp.id
from pp
where pp.day-(select max(day)
              from pp pp2
              where
                pp2.id=pp.id and
                pp2.day<pp.day)>=50

(因为天不是按键排序的,所以我不是在搜索前一个键,而是在当前日期之前的最大天数)

于 2012-11-28T11:15:12.523 回答