【问题标题】:SAP HANA Calculation View with Calculated Column with SQL ScriptSAP HANA 计算视图,带有 SQL 脚本的计算列
【发布时间】:2020-10-08 12:50:55
【问题描述】:

我在这个博客上创建了一个简历,就像这个“前成员”一样 https://blogs.sap.com/2017/05/18/factory-calendar-transpose-in-sap-hana-studio-step-by-step/

它就像一个魅力!

我的下一个要求是为每条记录获取 DATE_SAP 并确定会计月末;是的,我知道该值将在 30 天内保持不变。

我有一个可以工作的函数,可以为我提供会计月结束日期,但我似乎无法确定如何使其与我创建的 HANA CV 视图一起工作。

提前非常感谢!

这里是函数

CREATE FUNCTION "MY_SCHEMA"."FN_DTACCTMONTHEND"
(
    -- Add the parameters for the function here
dtexp date
)
RETURNS dtwkend date

LANGUAGE SQLSCRIPT
SQL SECURITY INVOKER AS

BEGIN
    -- Declare the return variable here
    DECLARE dttemp date;
    declare cnt int;
    declare c_dtwkend date;
    
Select ADD_DAYS(to_date('19000107', 'YYYYMMDD'),(FLOOR((days_between(to_date('19000107', 'YYYYMMDD'),:dtexp) / 7)) * 7) + 7) into c_dtwkend from dummy;
cnt := 0;

    while :cnt < 6 DO
    
        dttemp := add_days(:c_dtwkend,7);
        if MONTHNAME(:dttemp) = MONTHNAME(:c_dtwkend) then
             c_dtwkend := dttemp;
        else
             dtwkend := to_date(c_dtwkend);
             return;
        end if;         
        cnt := :cnt + 1;
    end while;

    -- Return the result of the function
    dtwkend := to_date(c_dtwkend);
    return;

END;

这里是表格函数:

CREATE FUNCTION "SCHEMA_NAME"."SCHEMA_NAME::FN_DTACCTMONTHEND_TEST" (DATE_SAP date ) 
    RETURNS TABLE (DTWKEND date)
    LANGUAGE SQLSCRIPT
    SQL SECURITY INVOKER AS
BEGIN

DECLARE dttemp date;
    DECLARE cnt int;
    DECLARE c_dtwkend date;
    DECLARE dtwkend date;


Select ADD_DAYS(to_date('19000107', 'YYYYMMDD'),(FLOOR((days_between(to_date('19000107', 'YYYYMMDD'),:DATE_SAP) / 7)) * 7) + 7) into c_dtwkend
from dummy;

cnt := 0;

    while :cnt < 6 DO
    
        dttemp := add_days(:c_dtwkend,7);
        if MONTHNAME(:dttemp) = MONTHNAME(:c_dtwkend) then
             c_dtwkend := dttemp;
        else
             dtwkend := to_date(c_dtwkend);
             return;
        end if;         
        cnt := :cnt + 1;
    end while;

    -- Return the result of the function

    dtwkend :=  to_date(c_dtwkend);
    RETURN
    SELECT dtwkend from dummy;

    
END;

收到的错误是 SAP DBTech JDBC:[2]:一般错误:应为表函数定义带有表达式的 RETURN 语句

【问题讨论】:

  • 函数中是否需要使用CV中的列?如果您使用 XSA,则可以将 TF 集成到 CV 中。否则,您必须在侧面计算并加入或在 CV 之上(将 CV 作为表函数的输入参数)。
  • 是的,我想使用我用来制作工厂日历的 CV 输出中的 DATE_SAP。我在 Hana 中创建了一个 TF,但我看到的只是你可以在 TF 中执行某些功能,例如插入或循环,这是查找 CV 中每个日期的会计月末所必需的
  • 然后可以从CV中选择TF中的相关列。在 TF 中计算,将输出添加到更多视图。在 2.0 中会容易得多,因为您可以在 1 个 CV 内完成所有操作,并将 CV 节点作为 TF 的输入和输出。
  • 对不起,我的意思是说您不能在 TF 中执行“插入”或循环之类的功能,如果您查看了上述问题中的功能,则需要这样做。
  • 您可以在 TF 中使用循环和选择进入。您不能使用 ddl 或 dml 操作(INSERT、UPDATE、DELETE)。

标签: hana hana-sql-script


【解决方案1】:

好的,根据评论,要求是找到给定月份的最后一个星期日

虽然 OP 认为要计算这个循环是必需的,并且 LAST_DAY 函数在这里没有用,但事实恰恰相反。

借助 LAST_DAYWEEKDAY 函数可以轻松计算一个月的最后一个星期日:

SELECT 
     current_date
   , LAST_DAY(current_date)
   , WEEKDAY (LAST_DAY(current_date)) AS weekday_of_last_day
   --
   , ADD_DAYS (LAST_DAY(current_date)
        ,  -( (WEEKDAY(LAST_DAY(current_date)) + 1)           -- how many days back to the last Sunday?
              * sign (6 - weekday(last_day(current_date)))    -- set to 0 if the day is a SUNDAY already as THIS is the last Sunday
            )
          )    AS last_sunday_of_month
FROM 
    dummy;


CURRENT_DATE|LAST_DAY(CURRENT_DATE)|WEEKDAY_OF_LAST_DAY|LAST_SUNDAY_OF_MONTH|
------------|----------------------|-------------------|--------------------|
  2020-11-01|            2020-11-30|                  0|          2020-11-29|

注意:所选列CURRENT_DATELAST_DAY(current_date)WEEKDAY_OF_LAST_DAY 仅用于演示目的。列表达式 LAST_SUNDAY_OF_MONTH 不需要它们。


在本例中,我使用CURRENT_DATE,但可以插入任何日期 - 计算方式相同。

首先,计算锚月的LAST_DAYWEEKDAYWEEKDAY 产生一个介于 0 和 6 之间的数字,表示从 MONDAY 开始的工作日,即 SUNDAY = 6。

如果当前工作日已经是 6 天(= 星期日),我们不需要减去任何天数即可得到该月的最后一个星期日。这是通过将偏移量乘以 6(星期日的工作日数)与当前日期的工作日之间的差值的 SIGN 来实现的。如果这个差值为正(即在 1 和 6 之间),则偏移量乘以 1,如果差值为 0,则偏移量乘以 0。

这意味着,ADD_DAYS 仅在当前日期还不是星期日时“返回上一个星期日”。

就是这样:不需要循环,也不需要 SQLScript 代码。此 SQL 表达式可用于普通 SQL 或计算视图中。

【讨论】:

  • 我一定会尝试实现这一点。非常感谢!!!
  • 如果 current_date 已经超过该月的最后一个星期日怎么办?正确的会计月份
  • 如果您能具体解释一下您的要求,那就太好了。切换到下一个“会计期间”并不是一个广为人知的标准概念。为此,您可以通过CASE 添加不同的代码路径,在其中检查条件并返回本月或下个月的最后一个星期日。仍然不需要任何程序。
【解决方案2】:

RETURN 是为表函数保留的。将 BREAK 用于 while 循环。 请在下面找到一个示例。

DROP FUNCTION "SCHEMA"."FN_DTACCTMONTHEND_TEST";

CREATE FUNCTION "SCHEMA"."FN_DTACCTMONTHEND_TEST" (DATE_SAP date ) 
    RETURNS TABLE (DTWKEND date)
    LANGUAGE SQLSCRIPT
    SQL SECURITY INVOKER AS
BEGIN

    DECLARE dttemp date;
    DECLARE cnt int := 0;
    DECLARE c_dtwkend date;
    DECLARE dtwkend date := ADD_DAYS(to_date('19000107', 'YYYYMMDD'),(FLOOR((days_between(to_date('19000107', 'YYYYMMDD'),:DATE_SAP) / 7)) * 7) + 7);


    while :cnt < 6 DO
    
        dttemp := add_days(:c_dtwkend,7);
        if 
            MONTHNAME(:dttemp) = MONTHNAME(:c_dtwkend) 
        then
             c_dtwkend := dttemp;
        else
             dtwkend := to_date(c_dtwkend);
             BREAK;
        end if;         
        
        cnt := :cnt + 1;
    
    end while;


    -- Return the result of the function
    RETURN
        SELECT 
            to_date(c_dtwkend) AS DTWKEND
        FROM
            dummy;

    
END;

【讨论】:

  • 在 SQLScript 中,SELECT ... INTO... FROM DUMMY 应该被使用。相反,只需将值分配给变量。例如。 c_dtwkend := ADD_DAYS(to_date('19000107', 'YYYYMMDD'),(FLOOR((days_between(to_date('19000107', 'YYYYMMDD'),:DATE_SAP) / 7)) * 7) + 7) 这节省了此分配的整个 SQL 解析/优化工作。
  • 感谢 Lars,很遗憾 SPS12 不支持它
  • 究竟是什么?直接分配? SPS12 绝对支持这一点。您使用的是 SPS12 的最新补丁吗?
  • 我的错,我再次尝试了你的语法。我在之前的尝试中犯了一个错误!很抱歉造成混乱,感谢您的回复!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-25
相关资源
最近更新 更多