【问题标题】:How to join these columns efficiently (many rows) MS SQL如何有效地连接这些列(多行) MS SQL
【发布时间】:2021-02-04 10:43:23
【问题描述】:

我有以下数据库架构:

Purchases          [PurchaseID, CustomerID, Date...]
PurchasesReturns   [PurchaseReturnID, PurchaseID, ...]

Purchases 包含大量行,而 PurchasesReturns 少得多。

我想计算一下,对于曾经进行过购买退货的每一位客户(并且只针对他们!),从他们第一次购买到每次购买退货的天数。输出示例:

PurchaseID | CustomerID | DaysFromCustomersFirstPurchase
--------------------------------------------------------
       1001|           1|                            215
       1002|           1|                            216
       1003|           1|                            218
       1004|           2|                            184
       1005|           2|                            188
       1007|           4|                             24
       1008|           5|                            102

注意 - 以上所有购买都已退回(它们的 ID 在 PurchasesReturns 表中)

注意 - 购买 1001,1002,1003 是在不同的日期进行的,因此从客户 1 进行第一次购买之日起的天数是不同的。

注意 - ID 3 的客户从未进行过购买退货,因此他的购买不存在。

我做了类似的事情,但我不确定这是正确的,并且肯定没有效率 - 它永远不会结束(几个小时的测试)。

SELECT s1.PurchaseID, s1.CustomerID,
    FIRST_VALUE(s1.[Date]) OVER (PARTITION BY s1.CustomerID ORDER BY s1.Date) AS [Date]
FROM (SELECT s2.PurchaseID, s2.CustomerID, s2.[Date]
    FROM Purchases s2
    WHERE s2.CustomerID IN
        (SELECT DISTINCT s3.CustomerID
        FROM Purchases s3 
        WHERE s3.PurchaseID IN
            (SELECT s4.PurchaseID FROM PurchasesReturns s4))) s1

另外 - 我只尝试获取第一次购买的日期,我必须添加天数。

感谢您的每一个建议。

【问题讨论】:

    标签: sql sql-server tsql


    【解决方案1】:

    您可以聚合purchases 表以获取第一个日期,然后是join

    select pr.*,
           datediff(day, p.first_date, pr.date) as days_to_return
    from purchasereturns pr join
         (select customerid, min(date) as first_date
          from purchases p
          group by customerid
         ) p
         on p.customerid = pr.customerid;
    

    编辑:

    您想要的是购买日期而不是退货日期的差额。为此:

    select pr.*,
           datediff(day, p.first_date, p.date) as days_to_return
    from purchasereturns pr join
         (select p.*,
                 min(date) over (partition by customerid) as first_date
          from purchases p
         ) p
         on p.purchaseid = pr.purchaseid;
    

    【讨论】:

    • 非常感谢!但是为了让一切清楚 - 我要计算的天差是客户的第一次购买和返回的每个购买(不是退货本身)之间的差异 - 我们感兴趣的两个日期都来自购买表。第二件事——PurchaseReturn 中没有 CustomerID,我们必须从 Purchase 中获取它。但是,这对你很有帮助:)
    • @pablo11pablo11 。 . .谢谢你的澄清。在这种情况下,窗口函数比聚合更合适。很高兴您在退货上有购买 ID。并非所有数据库都有这些信息。
    • 两个注意事项 - 我认为它仍然计算客户首次购买和退货之间的天数?我想在每次购买(在 PurchaseReturn 表中有一个返回)和客户的第一次购买之间进行计数。第二件事——我们希望对每个购买(有退货)都这样做,而不是对每个 PurchasesReturn。难道我们不必从采购表中选择它(并过滤它)吗?
    • @pablo11pablo11 。 . .我不明白第二个条件。如果一次购买可以有多个退货,那么聚合或select distinct 可能会满足您的需求。
    • 我很难解释。尽管如此 - 非常感谢你,你帮了我很多! :)
    猜你喜欢
    • 1970-01-01
    • 2016-12-02
    • 1970-01-01
    • 2016-05-15
    • 1970-01-01
    • 1970-01-01
    • 2014-02-16
    • 2020-09-05
    • 2020-03-18
    相关资源
    最近更新 更多