SQL:如何选择每个客户的最后购买的产品?

huangapple go评论102阅读模式
英文:

SQL: how to select last purchased product per client?

问题

  1. 考虑以下表结构:
  2. * `invoice`: id, client_id
  3. * `items`: id, invoice_id, name, date
  4. 我的目标是获取以下数据集:`client_id, name, date`,但`name``date`是对应于最后购买的产品的列。
  5. 我尝试了以下查询,但它没有产生正确的结果:
  6. SELECT
  7. i.client_id, ii.name, MAX(ii.date)
  8. FROM
  9. invoice i
  10. INNER JOIN
  11. invoice_item ii ON i.id = ii.invoice_id
  12. GROUP BY
  13. i.client_id;
英文:

Consider the following tables structure:

  • invoice: id, client_id
  • items: id, invoice_id, name, date

My goal is to get the following dataset: client_id, name, date but the name and date are the columns that correspond to the last purchased product.

I tried the following query, but it does not produce the correct result

  1. SELECT
  2. i.client_id, ii.name, MAX(ii.date)
  3. FROM
  4. invoice i
  5. INNER JOIN
  6. invoice_item ii ON i.id = ii.invoice_id
  7. GROUP BY
  8. i.client_id;

答案1

得分: 2

你没有提到你使用的RDBMS是什么 - 如果它支持CTE(通用表达式)和窗口函数(许多最常用的RDBMS都支持),你可以使用类似以下的代码:

  1. WITH Purchases AS
  2. (
  3. SELECT
  4. i.client_id, ii.name, ii.date,
  5. RowNum = ROW_NUMBER() OVER (PARTITION BY i.client_id ORDER BY ii.date DESC)
  6. FROM
  7. invoice i
  8. INNER JOIN
  9. invoice_item ii ON i.id = ii.invoice_id
  10. )
  11. SELECT
  12. p.client_id, p.name, p.date
  13. FROM
  14. Purchases
  15. WHERE
  16. p.RowNum = 1;

Purchases 是一个CTE - 类似于“一次性的内联视图”;使用 ROW_NUMBER 函数,你可以按 client_id 对数据进行“分区”,为每个客户的所有购买进行顺序编号,按购买日期降序排序 - 因此每个客户的最新购买将始终具有 RowNum = 1 - 这正是我从该CTE中选择的内容。

英文:

You didn't mention what RDBMS you're using - if it does support CTE's (Common Table Expressions) and windowing functions (many of the most used RDBMS do support it), you could use something like this:

  1. WITH Purchases AS
  2. (
  3. SELECT
  4. i.client_id, ii.name, ii.date,
  5. RowNum = ROW_NUMBER() OVER (PARTITION BY i.client_id ORDER BY ii.date DESC)
  6. FROM
  7. invoice i
  8. INNER JOIN
  9. invoice_item ii ON i.id = ii.invoice_id
  10. )
  11. SELECT
  12. p.client_id, p.name, p.date
  13. FROM
  14. Purchases
  15. WHERE
  16. p.RowNum = 1;

The Purchases is a CTE - sort of an "one-off, inline view"; using the ROW_NUMBER function, you "partition" your data by client_id, and all purchases for each client are sequentially numbered, ordered descendingly by purchase date - so the most recent purchase for each client will always have RowNum = 1 - and that's exactly what I select from that CTE.

huangapple
  • 本文由 发表于 2023年7月23日 15:17:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/76747047.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定