【问题标题】:Two SQL updates that use CASE statements and need to access previous rows to update the current one两个使用 CASE 语句的 SQL 更新,需要访问以前的行来更新当前行
【发布时间】:2021-08-17 00:12:50
【问题描述】:

我有一个带有 python 和 dash/plotly 的仪表板,它接收来自用户的输入,然后在 Google BigQuery 上运行查询。

其中一个查询更新一列 (POR_FT),使用其他列(POR_CORR 或 POR_CLEAN,具体取决于 case 语句),从仪表板输入的字符串 (cpi) 和更新后 POR_FT 的前几行(如果 rownumber != 1 )。该表已经创建了所有列,因此如果我运行查询,它将更新表中的值。

我试图用于这种情况的查询是:

    DECLARE cpi STRING DEFAULT "C";
    UPDATE `xx.yy.zz` t
    SET
    POR_FT = s.POR_FT
    FROM
    (
    SELECT
        RN,
        CASE
        WHEN RN = 1 AND cpi = "S" AND PAY_SHALE_COR = "PAY" THEN POR_CORR
        WHEN RN = 1 AND cpi = "C" AND PAY_CLEAN = "PAY" THEN POR_CLEAN
        WHEN RN = 1 THEN 0
        WHEN RN > 1 AND cpi = "S" AND PAY_SHALE_COR = "PAY" THEN (POR_CORR/5) + (LAG(POR_FT, 1, 0)  OVER(ORDER BY RN))
        WHEN RN > 1 AND cpi = "C" AND PAY_CLEAN = "PAY" THEN (POR_CLEAN/5) + (LAG(POR_FT, 1, 0)  OVER(ORDER BY RN))
        ELSE (LAG(POR_FT, 1, 0) OVER(ORDER BY RN))
        END
        AS POR_FT
    FROM
        `xx.yy.zz`
    WHERE
        DEPTH_M IS NOT NULL
    )
    s
    WHERE
    t.RN = s.RN

但不能正常工作,它不会更新列。在我提出的另一个问题上,我得到的答复是 LAG 不打算以这种方式使用,它可能需要一种递归方法。

用户在cpi上输入“C”时的基本计算是:如果rownumber为1并且PAY_CLEAN = “PAY”,那么它只是简单地获取POR_CORR列的值。如果 rn > 1 并且 PAY_CLEAN = "PAY",那么它将得到 POR_CLEAN 的值除以 5 加上前一行的 POR_FT 的值。否则,它只会返回上一行的 POR_FT 的值。

这是我的数据集的SAMPLE

预期的输出应如下所示:

另一个查询看起来非常相似:

    DECLARE cpi STRING DEFAULT "C";
    UPDATE `xx.yy.zz` t
    SET
    t.HPV_CUM = s.HPV_CUM
    FROM
    (
    SELECT
        DEPTH_M,
        RN,
        CASE
        WHEN RN < 5 AND cpi = "S" AND PAY_SHALE_COR = "PAY" THEN HPV_LAMINATED
        WHEN RN < 5 AND cpi = "C" AND PAY_CLEAN = "PAY" THEN HPV_CLEAN
        WHEN RN < 5 THEN 0
        WHEN RN > 4 AND cpi = "S" AND PAY_SHALE_COR = "PAY" THEN (HPV_LAMINATED/5) + (LAG(HPV_CUM, 1)  OVER(ORDER BY RN))
        WHEN RN > 4 AND cpi = "C" AND PAY_CLEAN = "PAY" THEN (HPV_CLEAN/5) + (LAG(HPV_CUM, 2)  OVER(ORDER BY RN))
        ELSE (LAG(HPV_CUM, 1) OVER(ORDER BY RN))
        END
        AS HPV_CUM
    FROM
        `xx.yy.zz`
    WHERE
        DEPTH_M IS NOT NULL
    )
    s
    WHERE
    t.RN = s.RN

所以,如果我能解决一个问题,我可能会在第二个问题上使用相同的东西。

我怎样才能做到这一点?

提前致谢!

【问题讨论】:

  • 这看起来很熟悉 ;) ,解释一下您的查询中什么不起作用。加上对您的逻辑的清晰解释(基于示例数据)
  • @eshirvana 是的,哈哈。您之前的一个非常适合这种情况,因为它只是添加 0.2 等等。这个问题中的那些 2 实际上甚至不会在更新中生成任何值。我的问题中的预期输出实际上是我的示例中的内容,除了在我的示例中对 POR_FT 没有任何价值。我将编辑我的问题以更好地解释计算。
  • @eshirvana 我编辑了我的问题。

标签: sql google-bigquery


【解决方案1】:

你也可以,同样的方法:

SELECT RN
    , SUM(CASE WHEN (cpi = "S" AND PAY_SHALE_COR = "PAY") then (POR_CORR/5) 
               when (cpi = "C" AND PAY_CLEAN = "PAY") THEN (POR_CLEAN/5) END) OVER (ORDER BY RN) 
    + SUM(CASE WHEN RN = 1 AND cpi = "S" AND PAY_SHALE_COR = "PAY"  then (POR_CORR * 4 /5)
            when RN = 1 AND cpi = "C" AND PAY_CLEAN = "PAY"  THEN POR_CLEAN* 4 /5) ELSE 0 end) OVER () NEW_Pay_FT
FROM `xx.yy.zz`
WHERE DEPTH_M IS NOT NULL

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    • 2012-05-07
    • 1970-01-01
    • 1970-01-01
    • 2013-05-13
    • 1970-01-01
    相关资源
    最近更新 更多