假设我有一张顾客表和一张购物表.每次购买都属于一位客户.我想在一份SELECT份声明中列出所有客户及其最后一次购买的 list .最佳实践是什么?关于建筑索引有什么建议吗?

请在回答中使用以下表格/列名:

  • 顾客:idname
  • 购买:idcustomer_iditem_iddate

在更复杂的情况下,通过将最后一次购买放入customer表来对数据库进行非规范化(性能方面)是否有益?

如果(购买)id保证按日期排序,那么可以使用类似LIMIT 1的语句来简化语句吗?

推荐答案

这是StackOverflow上经常出现的greatest-n-per-group个问题的一个例子.

以下是我通常建议的解决方法:

SELECT c.*, p1.*
FROM customer c
JOIN purchase p1 ON (c.id = p1.customer_id)
LEFT OUTER JOIN purchase p2 ON (c.id = p2.customer_id AND 
    (p1.date < p2.date OR (p1.date = p2.date AND p1.id < p2.id)))
WHERE p2.id IS NULL;

说明:给定第p1行,不应该有第p2行有相同的客户和更晚的日期(如果是领带,则不应该有更晚的id).当我们发现这是真的,那么p1是该客户最近购买的.

关于索引,我会在purchase个列(customer_iddateid)上创建一个复合索引.这可能允许使用覆盖索引进行外部连接.确保在您的平台上进行测试,因为优化依赖于实现.使用RDBMS的功能分析优化计划.例如,MySQL上的EXPLAIN.


有些人使用子查询而不是我上面展示的解决方案,但我发现我的解决方案更容易解决关系.

Sql相关问答推荐

根据另一列的值添加另一列的给定值

在SQL中向每个子字节组添加字节行

在SQL中将相同且紧挨着的元素进行分组

Select 非重复值并按条件排除行

动态组/转置

无法将发票与产品价格相关联

在Netezza SQL中将字符DataType转换为整型DataType

仅在日期相隔时递增(Oracle SQL)

删除行而不使数据库超载

Select 一个非零值减少重复

有没有办法在雅典娜中将字符串转换为 int ?

多行状态下的分组查询判断状态

COBOL\DB2作业(job)需要帮助?快来获取专业指导!

使用给定的变量对在循环中执行更新语句

为重复的项目编号显示正在处理

根据是否存在值组合分组并 Select 行

函数调用作为插入值语句中的参数

BigQuery Pivot 遗漏行

如何找到特定时间间隔内的最大和最小日期?

sql count distinct by column 和 sum false 和 true