【问题标题】:Teradata FIFO ScriptTeradata FIFO 脚本
【发布时间】:2013-06-12 18:53:04
【问题描述】:

有一个旧的堆栈帖子 (First-in-first-out (FIFO) inventory costing),其中包含基于集合的 Speed Phreakery:FIFO Stock Inventory SQL 问题:(https://www.simple-talk.com/sql/performance/set-based-speed-phreakery-the-fifo-stock-inventory-sql-problem/)。

我一直在尝试将它从 SQL Server 调整到 Teradata SQL,但发现:

(a) Teradata 只能处理一个 CTE with statement

(b) 你不能使用交叉应用

(c) 不能使用提示索引?

我的问题是:

Teradata 中是否有替代方案(易失性表除外)来绕过上述 (a)?

Terdata“Cross Join”和SQL Server中的Cross Apply一样吗?

有人将此脚本改编为 Teradata 吗?

【问题讨论】:

    标签: sql teradata fifo


    【解决方案1】:

    您的帖子已有几个月的历史了,但这可能对其他人也有用。

    当我记得几年前我将它移植到 Teradata 时,在 Teradata 的 Developer Exchange 上有一个类似的问题。快速搜索其他解决方案后,我找到了这篇文章。

    由于 Teradata 支持 ROWS UNBOUNDED PRECEDING(微软在 SS2012 中添加了这一点),结果变得更加简单:

    关于您的问题:

    a:CTE 可以被 Derived Tables 代替,它只是一种语法变化。

    b:CROSS/OUTER APPLY 是 SQL Server 专有语法,有时可以用 [OUTER] JOIN 代替,在这种情况下,它只是一种复杂的累积求和方式。

    c:当优化器没有做好计划时,索引提示应该是最后的手段

    SELECT
       ArticleId
      ,SUM(ItemCnt) AS CurrentItems -- same as TotalStock
      ,SUM(ItemCnt * CurrentPrice) AS CurrentValue
    FROM
     (
       SELECT
          ArticleId
    
         -- how many items will be used from this transaction, maybe less than all for the oldest row
         ,CASE WHEN RollingStock + Items > TotalStock THEN TotalStock - RollingStock ELSE Items END AS ItemCnt
    
         -- find the latest IN-price for RET rows
         ,MAX(Price)
          OVER (PARTITION BY ArticleID, PriceGroup
                ORDER BY TranDate) AS CurrentPrice
       FROM
        (
          SELECT
             ArticleId ,TranDate ,Price ,Items --,TranCode
    
            -- dummy column to get the current price in the next step, new group starts with every 'IN'
            ,SUM(CASE WHEN TranCode = 'IN' THEN 1 ELSE 0 END)
             OVER (PARTITION BY ArticleID
                   ORDER BY TranDate
                   ROWS UNBOUNDED PRECEDING) AS PriceGroup
    
            -- Aggregating all in/out movements -> number of items left in stock after all transactions
            ,SUM(CASE WHEN TranCode IN ('IN', 'RET') THEN Items ELSE -Items END)
             OVER (PARTITION BY ArticleID) AS TotalStock
    
            -- reverse sum of all inbound IN/RET movements
            ,SUM(CASE WHEN TranCode IN ('IN', 'RET') THEN Items END)
             OVER (PARTITION BY ArticleID)
            -SUM(CASE WHEN TranCode IN ('IN', 'RET') THEN Items END)
             OVER (PARTITION BY ArticleID
                   ORDER BY TranDate
                   ROWS UNBOUNDED PRECEDING) AS RollingStock
    /*
            -- same as above, simpler syntax, but different ORDER BY results in extra STATS step in explain
            ,COALESCE(SUM(CASE WHEN TranCode IN ('IN', 'RET') THEN Items END)
             OVER (PARTITION BY ArticleID
                   ORDER BY TranDate DESC
                   ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING),0) AS RollingStock
    */
    /*      -- cumulative sum, not needed to get the result
            ,SUM(CASE WHEN TranCode IN ('IN', 'RET') THEN Items ELSE -Items END)
             OVER (PARTITION BY ArticleID
                   ORDER BY TranDate
                   ROWS UNBOUNDED PRECEDING) AS CurrentItems
    */
          FROM Stock
          -- only keep the row needed to calculate the value
          -- plus all IN rows to find the current price for RET rows in the next step
          -- to exclude items out of stock: add "AND (TotalStock > 0)"
          QUALIFY ((TranCode = 'IN') OR (RollingStock <= TotalStock AND TranCode = 'RET'))AND (TotalStock > 0)
        ) AS dt
       -- remove older IN rows
       QUALIFY ItemCnt >= 0
     ) AS dt
    GROUP BY 1
    ORDER BY 1
    

    它基于与此处描述的获胜解决方案相同的逻辑: https://www.simple-talk.com/sql/performance/set-based-speed-phreakery-the-fifo-stock-inventory-sql-problem/

    这将运行得非常快,您不必创建 SQL Server 所需的任何索引 :-)

    将其移植到其他 DBMS 的备注:

    这是普通的标准 SQL,只有 QUALIFY 是 Teradata 特定的。 QUALIFY 与 GROUP BY 的 HAVING 相同,过滤 OLAP 函数的结果。可以通过将条件移动到外层的 WHERE 轻松替换它。

    【讨论】:

    • 这是对脚本的一个很好的改编,但它计算的是商品手头的成本,而不是商品售出的成本。
    • 嗯,这正是“FIFO Stock Inventory SQL 问题”应该解决的问题。库存剩余商品的价值是多少:-)
    【解决方案2】:

    您可以使用派生表代替 CTE

    【讨论】:

      猜你喜欢
      • 2012-08-05
      • 1970-01-01
      • 1970-01-01
      • 2021-08-18
      • 2020-04-27
      • 2014-09-13
      • 2017-02-22
      • 2012-04-24
      • 2020-05-21
      相关资源
      最近更新 更多