【问题标题】:SQL Join on table with revision datesSQL Join 与修订日期的表
【发布时间】:2020-04-06 00:53:37
【问题描述】:

我即将开始使用 SQL 为我的公司开发一个解决方案,该解决方案需要我根据 SKU 编号链接产品类别映射。问题是类别映射可以更改,并且它们将具有与更改相关联的日期。

例如:

  • 产品 1 当前映射到类别 A。
  • 用户意识到它是 映射错误并将产品 1 映射更改为类别 B 2018 年 1 月 1 日之后的所有交易。
  • 另一个用户决定将产品 1 映射到 C 类,但仅适用于 2019 年 2 月 1 日之后的交易。 等等……

最终,我需要将产品的销售额分配到发生销售时它所在的类别。

我想我可以像下面这样加入:

SELECT 
   A.TransactionDate,
   A.Product,  
   B.Category, 
   SUM(A.Sales) AS TotalSales 
FROM Products AS A 
JOIN CategoryMappings AS B ON 
   A.Product=B.Product AND 
   A.TransactionDate>=B.RevisionDate 
GROUP BY A.TransactionDate, A.Product, B.Category

这假设我正在获取每个月的销售额和类别映射,并且每个月的交易都发布到月底日期(“2018 年 1 月 31 日”、“2019 年 4 月 30 日”等)。不幸的是,如果只有一个映射更改,则此 Join 仅适用于最新事务,但是如果像示例中那样有三个或更多,该怎么办?如果我想根据 2018 年映射来查看 2018 年的销售额,因为它夹在其他两个映射之间,该怎么办?

我以前使用过 Stack Overflow,但这是我的第一个问题,如果缺少信息或格式不正确,请见谅。

感谢您提供的任何帮助!

【问题讨论】:

  • 嗨 Tyler,我会将映射表设计为包含 datefrom 和 dateto 字段,这样您就可以始终确保映射允许您及时移动
  • 感谢您的评论。不幸的是,我是用户而不是设计师。我正在等待访问服务器,但有人告诉我这是设置,我知道这是最终需要完成的。我当然希望这就是它的格式。如果是,查询将如何编写?我在脑子里想着,我只能为每个特定的映射段弄清楚,而不是整个表。
  • 在您的查询中,您说的是A.TransactionDate>=B.RevisionDate,但这似乎是一个缺陷,因为在您的示例中,您显示了产品 1 在 2018 年 1 月 1 日至 2019 年 2 月 1 日期间属于 B 类.你是怎么解释的?
  • 这就是我要问的问题。当只有两个时,我只能想出一种方法来提取最近的映射。我需要它更灵活。
  • 样本数据和期望的结果真的很有帮助。

标签: sql sql-server join mapping revision-history


【解决方案1】:

无法根据示例数据进行验证,不确定。

但我认为 NOT EXISTS 可能会限制为最近的修订版。

SELECT 
   P.TransactionDate,
   P.Product,  
   CatMap1.Category, 
   SUM(P.Sales) AS TotalSales 
FROM Products AS P
JOIN CategoryMappings AS CatMap1 
  ON CatMap1.Product = P.Product 
 AND CatMap1.RevisionDate <= P.TransactionDate

WHERE NOT EXISTS
(
    SELECT 1
    FROM CategoryMappings AS CatMap2
    WHERE CatMap2.Product = P.Product
      AND CatMap2.RevisionDate <= P.TransactionDate
      AND CatMap2.RevisionDate > CatMap1.RevisionDate
)

GROUP BY P.TransactionDate, P.Product, CatMap1.Category

CROSS APPLY 也可以工作

SELECT 
   P.TransactionDate,
   P.Product,  
   CatMap.Category, 
   SUM(P.Sales) AS TotalSales 
FROM Products AS P
CROSS APPLY
(
    SELECT TOP 1 CM.Category
    FROM CategoryMappings AS CM
    WHERE CM.Product = P.Product 
      AND CM.RevisionDate <= P.TransactionDate
    ORDER BY CM.RevisionDate DESC
) CatMap
GROUP BY P.TransactionDate, P.Product, CatMap.Category

【讨论】:

  • @TylerH 谢谢。顺便说一句,我更喜欢交叉应用。考虑在同一日期进行 2 次修订的情况。但是,如果RevisionDate 不是 DATETIME,那么它可能需要 ORDER BY 中的一个额外字段。 F.e. CM.Id
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-05-24
  • 2016-06-30
  • 1970-01-01
  • 1970-01-01
  • 2014-11-20
  • 2017-03-03
  • 2021-11-15
相关资源
最近更新 更多