我有一个相当复杂的查询,但为了完整起见,我将按原样发布:
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)
?
恐怕“我猜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 的演示涵盖了重构以提高可读性并附有大量示例。