【问题标题】:Joining two tables in SQL to get the SUM between two dates在 SQL 中连接两个表以获取两个日期之间的 SUM
【发布时间】:2021-05-22 10:35:39
【问题描述】:

我是 SQL 和这个网站的新手,如果有任何不清楚的地方,我们深表歉意。

基本上,我有两个单独的表:

表 A:

CustomerID | PromoStart | PromoEnd
1          | 2020-05-01 | 2020-05-30
2          | 2020-06-01 | 2020-07-30
3          | 2020-07-01 | 2020-10-15

表 B:

CustomerID | Date       | Payment |
1          | 2020-02-15 | 5000    |
1          | 2020-05-04 | 200     |
1          | 2020-05-28 | 100     |
1          | 2020-06-05 | 1000    |
2          | 2020-06-10 | 20      |
2          | 2020-07-25 | 500     |
2          | 2020-08-02 | 1000    |
3          | 2020-09-05 | 580     |
3          | 2020-12-01 | 20      |

我想要的是获得每个客户在PromoStart 和PromoEnd 之间的所有付款的总和。

所以想要的结果是:

CustomerID  | TotalPayments
1           | 300
2           | 520
3           | 580

我想这将涉及一个内部(左?)连接和一个 where 子句,但我就是想不通。

【问题讨论】:

  • 请始终披露您的 RDBMS 和版本。
  • SELECT table_b.CustomerId, SUM(Payment) FROM table_b JOIN table_a ON table_b.date BETWEEN table_a.promo_start AND table_a.promo_end。

标签: sql


【解决方案1】:

您可以使用关联子查询或 join 与聚合。相关子查询如下所示:

select a.*,
       (select sum(b.payment)
        from b
        where b.customerid = a.customerid and
              b.date >= a.promostart and
              b.date <= a.promoend
       ) as totalpayments
from a;

您没有提及您的数据库,但这可以利用b(customerid, date, payment) 上的索引。通过避免外部聚合,这通常比使用group by 的替代方案具有更好的性能。

【讨论】:

  • 非常感谢!我几乎使用了完全相同的查询,但我想我刚刚意识到它为什么不起作用 - PromoEnd 列缺少值。我将如何调整查询,使其仅在 a.promoend 不为空时使用 b.date
【解决方案2】:

LATERAL 加入就可以了:

SELECT a.customer_id, b.total_payments
FROM   table_a a
LEFT   JOIN LATERAL (
   SELECT sum(payment) AS total_payments
   FROM   table_b
   WHERE  customer_id = a.customer_id
   AND    date BETWEEN a.promo_start AND a.promo_end
   ) b ON true;

这假设包含上下限,并且您希望包含来自table_a 的所有行,即使table_b 中没有任何付款。

【讨论】:

    【解决方案3】:

    我希望我没有忽略一些重要的事情,但在我看来,范围匹配条件的简单连接就足够了:

    with a (CustomerID , PromoStart , PromoEnd) as (values
    (1          , date '2020-05-01' , date '2020-05-30'),
    (2          , date '2020-06-01' , date '2020-07-30'),
    (3          , date '2020-07-01' , date '2020-10-15')
    ), b (CustomerID , d       , Payment ) as (values
    (1          , date '2020-02-15' , 5000    ),
    (1          , date '2020-05-04' , 200     ),
    (1          , date '2020-05-28' , 100     ),
    (1          , date '2020-06-05' , 1000    ),
    (2          , date '2020-06-10' , 20      ),
    (2          , date '2020-07-25' , 500     ),
    (2          , date '2020-08-02' , 1000    ),
    (3          , date '2020-09-05' , 580     ),
    (3          , date '2020-12-01' , 20      )
    )
    select a.CustomerID, sum(b.Payment)
    from a
    join b on a.CustomerID = b.CustomerID and b.d between a.PromoStart and PromoEnd
    group by a.CustomerID
    

    Db fiddle here.

    【讨论】:

      猜你喜欢
      • 2022-01-24
      • 1970-01-01
      • 1970-01-01
      • 2017-06-12
      • 1970-01-01
      • 1970-01-01
      • 2010-10-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多