这并不明显,但您要解决的问题中缺少一些重要信息。当您考虑进入此表的实际数据时,它会变得更加明显。问题是您不太可能拥有一致的每日用户体重记录。因此,您需要澄清一些关于确定“当前体重”和“x 天前体重”的规则。我将假设以下简单的规则:
- 最近的重量读数是“当前重量”。 (尽管那可能是几个月前的事了。)
- x 天前的最新重量读数将是 x 天前假定的重量。 (例如,在确定 7 天前的体重时,6 天前的读数比 21 天前的读数更可靠。)
现在回答问题:
1&2:使用上述额外规则提供了生成两个结果集的机会:当前权重和以前的权重:
当前权重:
select rd.*,
w.Weight
from (
select User_id,
max(Created_at) AS Read_date
from Foodbar
group by User_id
) rd
inner join Foodbar w on
w.User_id = rd.User_id
and w.Created_at = rd.Read_date
x 天前的阅读类似:
select rd.*,
w.Weight
from (
select User_id,
max(Created_at) AS Read_date
from Foodbar
where Created_at < DATEADD(dd, -7, GETDATE()) /*Or appropriate MySql equivalent*/
group by User_id
) rd
inner join Foodbar w on
w.User_id = rd.User_id
and w.Created_at = rd.Read_date
现在只需将这些结果作为子查询加入
select cur.User_id,
cur.Weight as Cur_weight,
prev.Weight as Prev_weight
cur.Weight - prev.Weight as Weight_change
from (
/*Insert query #1 here*/
) cur
inner join (
/*Insert query #2 here*/
) prev on
prev.User_id = cur.User_id
如果我没记错的话,获得前 N 个体重增加的 MySql 语法是简单地添加:
ORDER BY cur.Weight - prev.Weight DESC limit N
2&3:选择索引需要稍微了解查询优化器将如何处理查询:
在选择索引时,重要的是您要过滤或加入的列。如果确定索引足够选择性,优化器将使用该索引(请注意,有时您的过滤器必须非常选择性地返回
3:尽管权重在您显示的内容中占有重要地位,但在过滤(或选择)方面唯一相关的是在 #2 中以获得前 N 个权重增益。这是一个基于大量查询和大量处理的复杂计算;所以权重作为指标将提供零收益。
另一个注意事项是,即使对于#2,您也必须计算所有用户的权重变化,以确定哪些用户获得的收益最大。因此,除非您的每个用户有大量读数,否则您将阅读该表的大部分内容。 (即表扫描将用于获取大量数据)
索引可以受益的地方:
- 您正在尝试根据 User_id 和 Created_at 识别特定的 Foodbar 行。
- 您还将使用 User_id 和 Created_at 再次加入到 Foodbar 表。
这意味着 User_id 上的索引,Created__at 将很有用(如果这是聚集索引,则更是如此)。
4:不,不幸的是,在数学上不可能确定单个值 H 和 W 如何独立确定产品的排序。例如。 H=3 和 W=3 均小于 5,但如果 H=5 且 W=1,则乘积 3*3 大于 5*1。
您必须将计算实际存储在该附加列上的索引中。但是,正如我在上面对 #3 的回答中指出的那样,它仍然不太可能证明是有益的。