我有一个MySQL表,用于存储来自用户数据的输入,并为每个提交的表单添加时间戳。
表格通常每天提交,但用户可以决定每天进行多次。
我必须显示一个显示过去6周数据的图表,或者,如果6周的数据不包含足够的数据点(40)我必须限制点数(它可以从早期获得数据点)日期)。
我可以在一个查询中执行此操作,还是应该依赖一些更复杂的SQL,或者更糟糕的是我必须依赖我的Python / PHP / C ++ / ... wathever?
回顾:
澄清:
答案 0 :(得分:1)
select t2.* from (
SELECT t.*,
@rownum := @rownum + 1 AS rownumber
FROM YOUR_TABLE t,
(SELECT @rownum := 0) r
ORDER BY timestamp
) as t2
where t2.rownumber<=40 or t2.timestamp >= '6-week-date'
答案 1 :(得分:1)
当然,有很多方法可以在一个查询中实现这一点,但我怀疑它是否可以高效地完成。假设您的表在日期/时间字段上编入索引,这样的查询应该是即时的:
SELECT COUNT(dateField) FROM myTable
WHERE dateField >= DATE_SUB(NOW(), INTERVAL 6 WEEK);
然后我将进行两次传递,并根据上述查询的返回值触发这两个版本中的任何一个:
-- if previous query returned < 40
SELECT * FROM myTable
ORDER BY dateField DESC
LIMIT 40;
或
-- if previous query returned >= 40
SELECT * FROM myTable
WHERE dateField >= DATE_SUB(NOW(), INTERVAL 6 WEEK);
通知:
NOW()
应该替换为您在流程开始时计算的一个litteral值(否则您将不会在时间过去时在相同的WHERE
条件下进行过滤)
第一个SELECT
语句实际上应该是一个锁定SELECT ... FOR UPDATE
语句,以便在获得真实数据(第二个查询)之前防止干扰。当然,这将在一次交易中发生。
答案 2 :(得分:0)
我会这样做:
SELECT t.*
FROM mytable t
CROSS
JOIN ( SELECT COUNT(1) AS cnt
FROM mytable ct
WHERE c.submitted_timestamp >= NOW() + INTERVAL -6 WEEK
) c
WHERE ( c.cnt <= 40 )
OR ( c.cnt > 40 AND t.submitted_timestamp >= NOW() + INTERVAL -6 WEEK )
ORDER
BY t.submitted_timestamp DESC
LIMIT 40
内联视图(上面指定了c
的别名)返回指定时间段(6周)内带时间戳的数量。
我们在外部查询的WHERE子句中使用为count返回的值。如果计数小于40,那么我们不包括任何其他谓词(获取所有行)。
如果计数大于40,那么我们包含一个额外的谓词。
ORDER BY向我们保证我们首先拥有最新的行。 LIMIT确保我们返回不超过40行。
(前导列为submitted_timestamp
的索引可能会提高效果。