SQL join: selecting the last records in a one-to-many relationship

前端 未结 10 1667
深忆病人
深忆病人 2020-11-22 08:48

Suppose I have a table of customers and a table of purchases. Each purchase belongs to one customer. I want to get a list of all customers along with their last purchase in

相关标签:
10条回答
  • 2020-11-22 09:36

    Without getting into the code first, the logic/algorithm goes below:

    1. Go to the transaction table with multiple records for the same client.

    2. Select records of clientID and the latestDate of client's activity using group by clientID and max(transactionDate)

         select clientID, max(transactionDate) as latestDate 
         from transaction 
         group by clientID
      
    3. inner join the transaction table with the outcome from Step 2, then you will have the full records of the transaction table with only each client's latest record.

         select * from 
         transaction t 
         inner join (
           select clientID, max(transactionDate) as latestDate
           from transaction 
           group by clientID) d 
         on t.clientID = d.clientID and t.transactionDate = d.latestDate) 
      
    4. You can use the result from step 3 to join any table you want to get different results.

    0 讨论(0)
  • 2020-11-22 09:38

    This is an example of the greatest-n-per-group problem that has appeared regularly on StackOverflow.

    Here's how I usually recommend solving it:

    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;
    

    Explanation: given a row p1, there should be no row p2 with the same customer and a later date (or in the case of ties, a later id). When we find that to be true, then p1 is the most recent purchase for that customer.

    Regarding indexes, I'd create a compound index in purchase over the columns (customer_id, date, id). That may allow the outer join to be done using a covering index. Be sure to test on your platform, because optimization is implementation-dependent. Use the features of your RDBMS to analyze the optimization plan. E.g. EXPLAIN on MySQL.


    Some people use subqueries instead of the solution I show above, but I find my solution makes it easier to resolve ties.

    0 讨论(0)
  • 2020-11-22 09:38

    Try this, It will help.

    I have used this in my project.

    SELECT 
    *
    FROM
    customer c
    OUTER APPLY(SELECT top 1 * FROM purchase pi 
    WHERE pi.customer_id = c.Id order by pi.Id desc) AS [LastPurchasePrice]
    
    0 讨论(0)
  • 2020-11-22 09:39

    Please try this,

    SELECT 
    c.Id,
    c.name,
    (SELECT pi.price FROM purchase pi WHERE pi.Id = MAX(p.Id)) AS [LastPurchasePrice]
    FROM customer c INNER JOIN purchase p 
    ON c.Id = p.customerId 
    GROUP BY c.Id,c.name;
    
    0 讨论(0)
提交回复
热议问题