更新:Kordirko的解决方案在SQL Fiddle中可以正常工作,但正如我的评论中所提到的,代码在我自己的mysql数据库中不起作用。我直接复制了架构命令,并从小提琴运行查询的副本。我检查了两个,它们是相同的代码。我在我的数据库和小提琴之间验证了相同的5.1.61 mysql版本。在实时数据库中,为id 2返回3行,而在小提琴上只返回2行(所需效果)。可以在传递之前改变查询吗?
背景
我有一张数据表,作为扫描结果的历史记录保存。通常它用于绘制结果随时间变化的趋势,但我想尝试别的东西。如果至少有2个数据点,我想提供最新趋势向上或向下(以百分比表示)。更具体地说,我还想将此限制在最近7天,以将趋势的范围限制在活跃的项目中。
请注意,该表仅在项目第一次运行时更新,并且如果issues_count已从上一次运行更改。
样本表:
id issues_count updated
1 7922 2013-10-02 08:22:31
1 7981 2013-10-03 08:22:43
2 7754 2013-10-10 12:06:45
2 7922 2013-10-11 12:06:45
2 7981 2013-10-12 02:09:43
3 15536 2013-10-12 02:09:43
4 1233 2013-10-11 12:06:45
4 2493 2013-10-12 02:09:43
5 4349 2013-10-12 02:09:44
表格结构:
CREATE TABLE IF NOT EXISTS `issue_history` (
`id` bigint(20) unsigned NOT NULL,
`issues_count` mediumint(8) unsigned NOT NULL,
`updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
KEY `id_index` (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=ascii;
结果逻辑:
在上面的示例中,我想忽略两个'1'id条目,因为它们超过7天(从今天开始)。我想不为id'3'和id'5'返回任何内容,因为它们到目前为止只有一个数据点。对于ids'2'和'4',我希望根据时间戳(不是之前的任何内容,最多2个)返回最新的和最接近它的那个。
示例结果:
2 7922 2013-10-11 12:06:45
2 7981 2013-10-12 02:09:43
4 1233 2013-10-11 12:06:45
4 2493 2013-10-12 02:09:43
其他想法:
顺序并不重要,尽管我可能希望先将它们分组为id(asc或desc),然后再分配给desc中的时间戳。
如果我要进行低效的尝试,我可以通过在过去24小时内对所有ID进行选择来处理此问题,然后可以选择与这些ID匹配的所有行,按时间戳desc排序,限制2.然后我的代码必须删除每个id少于2行的结果。可能我会追求从第一个中选择子查询并嵌入到第二个中。我仍然认为这不是最好的方法,但应该起作用。
我担心的是这个表可能会以每天几千行的速度增长,我想尝试花费最少的时间来运行该命令。我特别不想从程序中击中数据库两次。
答案 0 :(得分:1)
尝试此查询:
SELECT id,
issues_count,
updated
FROM (
SELECT sub1.*,
IF(@last_id=sub1.id,(@rn:=@rn+1),(@rn:=1)) rn,
(@last_id:=sub1.id) last_id
FROM (
SELECT ih.*
FROM issue_history ih
JOIN (
SELECT id
FROM issue_history
-- the most recent 7 days
WHERE updated > now() - interval 7 day
GROUP BY id
-- if there are at least 2 data points
HAVING count(*) >= 2
) ih1
ON ih.id = ih1.id AND ih.updated > now() - interval 7 day
CROSS JOIN ( SELECT (@rn:=0),(@last_id=-12345)) init_variables
) sub1
-- by id (asc or desc) and then by the timestamp in desc
ORDER BY sub1.id ASC, sub1.updated DESC
) subquery
-- not any prior to that, 2 max
WHERE rn <= 2
ORDER BY id ASC, updated ASC
演示---&gt; http://www.sqlfiddle.com/#!2/4309b/30
-------编辑------------
确定该对的最新日期并按此日期对记录进行排序的另一个版本
SELECT id,
issues_count,
updated,
most_recent_date
FROM (
SELECT sub1.*,
IF(@last_id=sub1.id,(@rn:=@rn+1),(@rn:=1)) rn,
(@last_id:=sub1.id) last_id
FROM (
SELECT ih.*, ih1.most_recent_date
FROM issue_history ih
JOIN (
-- max( updated ) --> most recent date
SELECT id, max( updated ) most_recent_date
FROM issue_history
-- the most recent 7 days
WHERE updated > now() - interval 7 day
GROUP BY id
-- if there are at least 2 data points
HAVING count(*) >= 2
) ih1
ON ih.id = ih1.id AND ih.updated > now() - interval 7 day
CROSS JOIN ( SELECT (@rn:=0),(@last_id=-12345)) init_variables
) sub1
-- by id (asc or desc) and then by the timestamp in desc
ORDER BY sub1.id ASC, sub1.updated DESC
) subquery
WHERE rn <= 2
ORDER BY most_recent_date, id, updated
演示 - &gt; http://www.sqlfiddle.com/#!2/1eb9fe/1