如何在联接中仅使用满足条件的第一个值?

How do I use just the first value that satisfies a condition in my join?

提问人:snappymcsnap 提问时间:11/7/2023 更新时间:11/7/2023 访问量:47

问:

我试着思考最有效的方法是什么,希望你能提供帮助。我有两个表,一个是客户呼叫数据(客户呼叫客户服务号码),另一个是发票数据。它们来自不同的来源,因此没有共享的 PK-FK 关系。下面是一些示例数据:

呼叫数据

呼叫 ID 电话号码 呼叫日期
12345 555-555-5555 互联网 2023-11-06
12346 555-666-6666 转 介 2023-01-01
12347 555-666-6666 转 介 2023-02-02
12348 555-666-6666 互联网 2023-05-17
12349 555-777-7777 转 介 2023-10-31
12350 555-777-7777 互联网 2023-11-03

发票

发票 Id 电话号码 发票日期
11111 555-555-5555 250.56 2023-01-01
22222 555-666-6666 376.67 2023-02-01
33333 555-666-6666 761.09 2023-06-02
44444 555-666-6666 316.23 2023-07-03
55555 555-777-7777 145.33 2023-10-01
66666 555-777-7777 986.92 2023-11-01

我需要能够根据 PhoneNumber 将这两者连接在一起。但我只关心 CallData.Source = 'referral' 的记录,这样就消除了上面除了 3 个 CallData 记录之外的所有记录。然后,我想对所有 Invoice.Amount 值求和,但前提是 InvoiceDate 至少大于 CallDates 之一。

因此,请考虑电话号码为 555-666-6666 的 CallData 记录,有 2 个是引用类型,它们的 CallDates 为:

  • 2023-01-01
  • 2023-02-02

在 Invoice 表中,有 3 张发票的 InvoiceDates 为:

  • 2023-02-01
  • 2023-06-02
  • 2023-07-03

我所关心的是,所有 3 个 InvoiceDates 都在至少一个匹配的 CallDates(在本例中为 2023-01-01)之后,所以我会将所有三个相加并得到 1453.99。

如果您有任何其他问题,请告诉我,谢谢

SQL MySQL 联接

评论

0赞 Stu 11/7/2023
你试过什么吗?

答:

-1赞 Luuk 11/7/2023 #1

您没有指定所需的输出,因此:

SELECT DISTINCT
   CallId,
   CallData.PhoneNumber,
   SUM(Amount) OVER (Partition BY CallId,CallData.PhoneNumber)  as "sum"
   
FROM CallData
INNER JOIN Invoice ON Invoice.PhoneNumber = CallData.PhoneNumber 
                  AND Invoice.InvoiceDate > CallData.CallDate
WHERE CallData.Source = 'referral'
  ;

输出:

呼叫 ID 电话号码
12346 555-666-6666 1454
12347 555-666-6666 1077
12349 555-777-7777 987

请参见:DBFIDDLE

此 SQL 语句的 90% 是您在问题中写的内容到 SQL 语法的字面翻译。

或者,仅通过电话号码:

SELECT DISTINCT

   CallData.PhoneNumber,
   SUM(Amount) OVER (Partition BY CallData.PhoneNumber)  as "sum"
   
FROM CallData
INNER JOIN Invoice ON Invoice.PhoneNumber = CallData.PhoneNumber 
                  AND Invoice.InvoiceDate > CallData.CallDate
WHERE CallData.Source = 'referral'
  ;

请参见:DBFIDDLE

评论

0赞 snappymcsnap 11/7/2023
对不起,应该在输出上更清楚,这很接近,但它不应该按 CallId 求和,而应该按 PhoneNumber 求和......所以 555-666-6666 = 1454 和 55-777-7777 = 987
0赞 Luuk 11/7/2023
查看电话号码,因此 555-666-6666 的总和将是 2531
1赞 user1191247 11/7/2023 #2

您可以使用 MIN() 来获取每个 PhoneNumber 的最小 CallDate:

SELECT Calls.*, SUM(Invoice.Amount) AS Amount
FROM (
    SELECT PhoneNumber, MIN(CallDate) AS MinCallDate
    FROM CallData
    WHERE Source = 'referral'
    GROUP BY PhoneNumber
) Calls
JOIN Invoice
    ON Invoice.PhoneNumber = Calls.PhoneNumber 
   AND Invoice.InvoiceDate >= Calls.MinCallDate
GROUP BY Calls.PhoneNumber;

输出:

电话号码 MinCallDate
555-666-6666 2023-01-01 1453.99
555-777-7777 2023-10-31 986.92

这是一个 db<>小提琴