SQL 結合: 1 対多の関係の最後のレコードを選択する 質問する

SQL 結合: 1 対多の関係の最後のレコードを選択する 質問する

顧客テーブルと購入テーブルがあるとします。各購入は 1 人の顧客に属します。1 つのSELECTステートメントですべての顧客のリストと最後の購入を取得したいと考えています。ベスト プラクティスは何ですか? インデックスの作成に関するアドバイスはありますか?

回答には次の表/列名を使用してください。

  • お客様:idname
  • 購入:idcustomer_iditem_iddate

さらに複雑な状況では、最後の購入を顧客テーブルに入れてデータベースを非正規化すると (パフォーマンスの面で) 有利になりますか?

(購入) がid日付順にソートされることが保証されている場合、次のようなものを使用してステートメントを簡略化できますかLIMIT 1?

ベストアンサー1

greatest-n-per-groupこれは、StackOverflow で定期的に発生する問題の例です。

通常、私は次のように解決することをお勧めします。

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は存在しないはずです。これが真であると判明した場合、 はその顧客の最新の購入になります。p2idp1

purchaseインデックスに関しては、列 ( customer_id​​、、 )に複合インデックスを作成します。これにより、カバーリング インデックスdateid使用して外部結合を実行できるようになります。最適化は実装に依存するため、必ずプラットフォームでテストしてください。RDBMS の機能を使用して、最適化プランを分析します。たとえば、EXPLAINMySQL の場合です。


上記で示した解決策の代わりにサブクエリを使用する人もいますが、私の解決策の方が同点の解決が容易になると思います。

おすすめ記事