【问题标题】:Equivalent to subquery without TOP or ORDER BY in HANA SQL相当于 HANA SQL 中没有 TOP 或 ORDER BY 的子查询
【发布时间】:2016-06-13 15:11:43
【问题描述】:

SAP SQL 转换器给了我这个作为输出:

SELECT c."id", c."key_link", 
    (SELECT TOP 1 "notes_extra" 
    FROM "Orders" c2 
    WHERE c2."id" = c."id" AND c2."start" < c."start" 
    ORDER BY c2."start" DESC) AS "previous_notes" 
FROM "Orders" c
ORDER BY c."id";

很遗憾,SAP HANA SPS 10 不接受它:
SAP DBTech JDBC:[309]:相关子查询不能有 TOP 或 ORDER BY

我正在努力将查询转换为没有 TOP 和 ORDER BY 的内容。用WHERE "start" = (SELECT MAX("start") 尝试了一些东西,但由于“开始”可能有重复的值,我最终得到:SAP DBTech JDBC:[305]:单行查询返回不止一行

那么 HANA SQL 中正确的等价物是什么?

编辑:
“notes_extra”列的类型为 NCLOB 似乎增加了问题。我尝试在此列上的聚合函数(MAX,FIRST_VALUE,...)中的某个点提出任何替代方案,这会导致:SAP DBTech JDBC:[264]:无效数据类型:LOB 输入聚合函数

【问题讨论】:

    标签: sql subquery hana


    【解决方案1】:

    “我不在乎”不是数据库擅长处理的事情。如果没有选项来实际决定取哪一行,那么数据模型根本不适合回答这个问题。

     select "id", "notes_extra" from 
         (SELECT c."id", c."notes_extra" 
                , row_number () over 
                   (partition by c."id" 
                    ORDER BY c."id" asc , c."start" desc) as RN 
          FROM orders c ) 
      where rn =2;
    

    可以根据一般排序交付倒数第二个订单。请注意,这会提供与您的初始查询相同的默认决胜局行为,即:任意。

    【讨论】:

      【解决方案2】:

      您根本不需要子选择,而是使用window function

      SELECT c."id", c."key_link", 
             lag(c."notes_extra") over (partition by c."id" order by c."start" desc) as "previous_notes" 
      FROM "Orders" c
      ORDER BY c."id";
      

      【讨论】:

      • 有趣!不幸的是,在我的情况下,“notes_extra”不适合:SAP DBTech JDBC: [264]: invalid datatype: "C.notes_extra" LOB type of "previous_notes" cannot be used - 这也排除了所有GROUP BY "notes_extra" 方法。 :\
      【解决方案3】:

      如果您仅按给定排序顺序查找“第一”列,则始终可以使用 max()/min() 聚合。不确定您遇到了什么问题,但这绝对是可能的。 但是,根据您的要求,我建议在 SQL 视图中实现逻辑(并将其与您的主查询连接)或作为表 udf。

      【讨论】:

      • WHERE c2."start" = (SELECT MAX(c3."start") FROM "Orders" c3) 这可能会返回多行,因为有多行具有相同的最大“开始”值,即使添加其他条件也是如此。这会导致一条错误消息,因为对于选择列表,必须只返回一个结果行。我在原始问题中添加了错误消息。
      • 显然你需要一个决胜局。如果返回多条记录,必须取哪一条?如果您的初始代码有效,那将是未定义的。
      • 拉斯:是的。那么,如果我真的不在乎,我该如何选择拍摄哪一张呢?请参阅上面的编辑。
      • “我不在乎”不是数据库擅长处理的事情。如果没有选项来实际决定取哪一行,那么数据模型根本不适合回答这个问题。 select "id", "notes_extra" from (SELECT c."id", c."notes_extra" , row_number () over (partition by c."id" ORDER BY c."id" asc , c."start" desc) as RN FROM orders c ) where rn =2; 可以按照一般排序的顺序发货倒数第二个。请注意,这会提供与您的初始查询相同的默认打破平局行为,即:任意。
      • Lars:row_number() over 方法确实有效,感谢您的提示!我最终优化了应用程序以处理所有行,不仅是“任何第一行”,而且您的评论与最初的问题相匹配,包括。所有约束最好。把它放在一个答案中,它就会被选中。
      【解决方案4】:

      您现在可以为此使用FIRST_VALUE() 函数,如下所示:

      SELECT (FIRST_VALUE(col ORDER BY col) FROM ... WHERE ...) AS ...

      【讨论】:

        猜你喜欢
        • 2015-02-01
        • 2016-04-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多