【问题标题】:How to use SQL find first matching result from one table in another table?如何使用 SQL 从另一个表中的一个表中查找第一个匹配结果?
【发布时间】:2020-10-22 13:32:09
【问题描述】:

假设我有两张桌子:

Customer -
ID  | Name  | Etc
1   | One   |
2   | Two   |
3   | Three |
4   | Four  |
5   | Five  |
... | ...   |

Sales - 
Customer ID | Date | Amount
5           | 1/20 | $45
5           | 3/19 | $145
3           | 8/19 | $453
7           | 3/20 | $4513
3           | 9/20 | ...
1           | 3/20 | ...
1           | 1/20 | ...

我想做的是编写一个查询,为每个客户找到第一笔销售。我不确定该怎么做。我觉得这是按问题分组的,但我没有找到答案。

编辑: 我觉得我的第一个数据表并没有完全解释我的问题。 (老实说,在我编写解决方案之前,我什至没有意识到我的问题的这一方面)注意:每次销售有多个客户。

Sales - 
Sale ID | Customer ID | Date | Amount
1       | 5           | 1/20 | $45
5       | 5           | 3/19 | $145
8       | 3           | 8/19 | $453
7       | 7           | 3/20 | $4513
3       | 4           | 9/20 | ...
2       | 1           | 3/20 | ...
1       | 1           | 1/20 | ...

【问题讨论】:

  • (很明显,)这是一个常见问题解答。请在考虑发布之前阅读您的教科书和/或手册和谷歌任何错误消息或您的问题/问题/目标的许多清晰、简洁和精确的措辞,有和没有您的特定字符串/名称和站点:stackoverflow.com 和标签;阅读许多答案。如果您发布问题,请使用一个短语作为标题。反映你的研究。请参阅How to Ask 和投票箭头鼠标悬停文本。对于代码,请提供minimal reproducible example
  • 我意识到我的问题更复杂。我每个订单有多个客户,而不仅仅是每个客户的多个订单。我会问一个新问题。
  • 请在代码问题中给出minimal reproducible example--cut & paste & runnable code,包括最小的代表性示例输入作为代码;期望和实际输出(包括逐字错误消息);标签和版本;明确的规范和解释。给出尽可能少的代码,即您显示的代码可以通过您显示的代码扩展为不正常的代码。 (调试基础。)对于包含 DBMS 和 DDL(包括约束和索引)和输入为格式化为表的代码的 SQL。 How to Ask 暂停整体目标的工作,将代码砍到第一个表达式,没有给出你期望的内容,说出你期望的内容和原因。

标签: sql oracle group-by partition


【解决方案1】:

您可以使用子查询为每个客户的每次销售分配一个行号,按日期升序排序,然后只选择第一行:

SELECT "Customer ID", "Date", "Amount"
FROM (
  SELECT "Customer ID", "Date", "Amount",
         ROW_NUMBER() OVER (PARTITION BY "Customer ID" ORDER BY "Date") AS rn
  FROM Sales) s
WHERE rn = 1

Demo on SQLFiddle

【讨论】:

    【解决方案2】:

    Nick 的解决方案可能是最高效的,但如果您想在这里使用GROUP BY,您可以这样做:

    SELECT
        c.ID,
        c.Name,
        s1.Date,
        s1.Amount
    FROM Customer c
    INNER JOIN Sales s1 ON c.ID = s1."Customer ID"
    INNER JOIN
    (
        SELECT "Customer ID", MIN(Date) AS FirstSaleDate
        FROM Sales
        GROUP BY "Customer ID"
    ) s2
        ON s1."Customer ID" = s2."Customer ID" AND
           s1.Date = s2.FirstSaleDate
    ORDER BY
        c.ID,
        c.Name;
    

    【讨论】:

    • 我意识到我的问题更复杂。我每个订单有多个客户,而不仅仅是每个客户的多个订单。我会问一个新问题。
    • 抱歉,我意识到尼克的答案适用于更多情况,包括我的情况。不过谢谢你,你的帮助我更好地理解了这个问题。
    【解决方案3】:

    在Oracle中,你可以使用keep:

    select customer_id, min(date) as first_sales_date,
           max(amount) keep (dense_rank first order by date asc) as first_amount
    from sales
    group by customer_id;
    

    【讨论】:

    • 不知道为什么蒂姆和我得到了投票,但你没有(当然除非是你),但让我更正一下......
    • @尼克。 . .嗯,谢谢。我的回答要晚得多——我实际上认为是在你的回答被接受之后。我只是提供它是因为它在 Oracle 中似乎是合理的,并且应该是其中的一种可能性。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-16
    • 2012-04-24
    • 1970-01-01
    • 2017-02-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多