回答

收藏

SQL连接:选择一对多关系中的最后一条记录

技术问答 技术问答 133 人阅读 | 0 人回复 | 2023-09-13

假设我有一个客户表和一个采购表。每次购买都属于一个客户。我想在一份SELECT声明中列出所有客户以及他们最近一次购买的清单。最佳做法是什么?关于建立索引有什么建议吗?0 T& V; b/ l  z8 I" G0 j
请在您的答案中使用这些表/列的名称:# Y/ H9 y6 b8 V* L5 ~
客户:id,name3 d/ J, Y; T% ]# N; P+ k
购买:id,customer_id,item_id,date
+ v7 G$ O9 i- M9 b

5 j! G; d5 X& |5 y+ P* _并且在更复杂的情况下,通过将最后一次购买放入客户表中来对数据库进行非规范化(在性能方面)是否有益?5 u2 N* u& J$ k+ F& e% q$ n( o- h5 S
如果id保证按日期将(购买)排序,可以使用类似的语句来简化语句LIMIT 1吗?
. f0 r8 ^/ l$ N0 t  \5 C7 b                + ]' F5 h' k+ r- s
解决方案:8 [" q* A/ I% @# ~! |- p; v
                5 M$ E% S3 {8 H8 P1 }9 n

) y9 c( H; c8 V* g' ^- X) W3 ~* w( w0 K
                这是greatest-n-per-group在StackOverflow上经常出现的问题的一个示例。
: a+ S5 V' L5 t5 q/ t* e! P7 x这通常是我建议解决的方式:
- m6 S" M) z) V/ G4 aSELECT c.*, p1.*, _0 |- K- j# P
FROM customer c+ j/ N2 O/ D" Y7 B
JOIN purchase p1 ON (c.id = p1.customer_id)" c6 i/ O- k" k$ w2 K
LEFT OUTER JOIN purchase p2 ON (c.id = p2.customer_id AND
! U5 [) _2 {" j1 u6 _; f    (p1.date 说明:给定一行p1,就不应有p2同一位客户和更晚的日期(或者在有联系的情况下,更晚的日期id)。当我们发现这是事实时,则p1是该客户的最近一次购买。, D: y% d9 j) H6 G2 I( X) c# y
对于指数,我会在创建复合指数purchase在列(customer_id,date,id)。这可以允许使用覆盖索引来完成外部联接。确保优化在您的平台上进行测试,因为优化取决于实现。使用RDBMS的功能来分析优化计划。例如EXPLAIN在MySQL上。4 w0 L2 D) a' f; c7 k$ [

; H0 {- J6 e8 ^. S) W有些人使用子查询来代替我上面显示的解决方案,但是我发现我的解决方案可以更轻松地解决联系。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则