在sap hana中使用聚合函数时如何保留对应的值?

问题描述 投票:0回答:1

我有一个相当复杂的查询,但为了完整起见,我将按原样发布:

WITH cte AS 
(
    SELECT
        t.ID, t.TYPE, t.DATE, COUNT(*) AS count_30_days
    FROM 
        ASQ_AFTERSALES.TYPE AS t
    INNER JOIN 
        ASQ_AFTERSALES.TYPE i ON t.DATE >= ADD_DAYS (i.DATE, -30)
                              AND t.DATE <= i.DATE
                              AND t.TYPE = i.TYPE
    GROUP BY 
        t.ID, t.TYPE, t.DATE
)
SELECT 
    TYPE, MAX(count_30_days) AS max_incidence
FROM 
    cte
GROUP BY 
    TYPE

这里发生的情况是,我将滚动窗口应用于“日期”列,并计算过去 30 天内的发生次数。 从这些值中,我希望获得每种类型的最大值。

这就是周围的陈述的目的(这是有趣的)。

当然,在计算最大值之前我有多行,但我想获取列 count_30_days 的最大值,同时也获取相应的日期。

WITH cte AS 
(
    SELECT
        t.ID, t.TYPE, t.DATE, COUNT(*) AS count_30_days
    FROM 
        ASQ_AFTERSALES.TYPE AS t
    INNER JOIN 
        ASQ_AFTERSALES.TYPE i ON t.DATE >= ADD_DAYS (i.DATE, -30)
                              AND t.DATE <= i.DATE
                              AND t.TYPE = i.TYPE
    GROUP BY 
        t.ID, t.TYPE, t.DATE
)
SELECT 
    TYPE, MAX(count_30_days) AS max_incidence, DATE
FROM 
    cte
GROUP BY 
    TYPE, DATE

运行此查询,出现以下错误:

单行子查询返回多行。

这是有道理的。我需要这样的东西:

WITH cte AS 
(
    ...
)
SELECT 
    TYPE, MAX(count_30_days) AS max_incidence, DATE
FROM 
    cte
GROUP BY 
    TYPE, MAX(DATE) KEEP (dense_rank first order by max_incidence desc)

但是这会引发错误,“(”附近的语法错误。我猜dense_rank函数或其他不同的函数在hana上不起作用?谢谢。

如何获取

DATE
行对应的
MAX(count_30_days)

sql max aggregate common-table-expression hana
1个回答
0
投票

恐怕“我猜KEEP应该是相当普遍的?”的假设与现实不符。

事实证明,

KEEP
语法属于 Oracle 的
FIRST
LAST
函数,这些函数 not 与 SQL 标准中描述的分析函数
FIRST_VALUE
LAST_VALUE
相混淆(并实现了包括 HANA 在内的许多 DBMS)。

在研究这个问题时,我在 SO 中找到了几个条目:

讨论此功能的地方。 其中还有一篇信息丰富的博客文章Keep Clause的链接,详细解释了该功能。

现在SAP HANA还没有实现这个功能。

为了达到预期的结果,人们必须依赖经常提到的“从有序/排序集中选择第一条记录”问题的通用解决方案:为排序的每个条目生成行号仅设置并选择结果为

row number = 1
的记录:

由于问题不包含任何测试数据,我必须自己编写,但这个例子应该说明方法:

WITH cte AS 
(
    SELECT
        t.ID, t.TYPE, t.DATE, COUNT(*) AS count_30_days
    FROM 
        ASQ_AFTERSALES AS t
    INNER JOIN 
        ASQ_AFTERSALES i ON t.DATE >= ADD_DAYS (i.DATE, -30)
                              AND t.DATE <= i.DATE
                              AND t.TYPE = i.TYPE
    GROUP BY 
        t.ID, t.TYPE, t.DATE
),
ranked_cte AS (
    SELECT TYPE, DATE, MAX(count_30_days)
    , ROW_NUMBER() OVER (PARTITION BY TYPE ORDER BY MAX(count_30_days) desc) AS rn
    FROM  cte
    GROUP BY TYPE, DATE

)
SELECT 
    *
FROM 
    ranked_cte
WHERE rn =1 
ORDER BY 
    TYPE, date ;

顺便说一句:我尽量避免在 SQL 语句中使用 SQL/HANA 关键字(如

"TYPE"
"DATE"
)作为标识符。这可能会导致混淆是引用了数据库功能还是数据模型。这些术语也非常通用,并且为当前的查询使用更具体的名称通常会导致代码更容易理解。

这种“特定命名”可以扩展到用于 hte CTE 的名称 - 而不是

cte
ranked_cte
,人们可以考虑使用
transaction_counts_30days
top_transaction_counts_30days

几年前我在 SAP Inside Track Melbourne 的演示涵盖了重构以提高可读性并附有大量示例。

© www.soinside.com 2019 - 2024. All rights reserved.