我想在我的 JasperReport 查询之一上使用 DENSE_RANK()
函数,但它不适用于 Firebird 2.5。但有一个example on the firebirdfaq.org site使用聚合函数和上下文变量或生成器来模拟此函数。即
SELECT p.name, p.score, COUNT(DISTINCT others.score) + 1 AS "dense_rank"
FROM players p
LEFT JOIN players others ON others.score > p.score
GROUP BY 1, 2
ORDER BY "dense_rank"
所以这是玩家的 self 加入。
我的问题是我没有像“玩家”这样的已定义表来进行自连接,但我的查询使用两个表。我尝试创建别名并使用子查询进行自连接,但没有成功。
SELECT x.DateCompleted, x.TimeCompleted, x.numOfBatches, COUNT(DISTINCT others.DateCompleted) + 1 AS "dense_rank"
FROM
(SELECT floor(PRODUCEDH.COMPLETE_TIME)+cast('30.12.1899' AS TIMESTAMP) AS DateCompleted,
(ABS(PRODUCEDH.COMPLETE_TIME) - FLOOR(ABS(PRODUCEDH.COMPLETE_TIME)))+cast('30.12.1899' AS TIMESTAMP) AS TimeCompleted,
COMMODITIES.CODE,
COMMODITIES.NAME AS COMMODITY_NAME,
(SUM(PRODUCEDH.MIXSIZE) / 100) as numOfBatches
FROM
"PRODUCEDH" "PRODUCEDH",
"COMMODITIES" "COMMODITIES"
WHERE
PRODUCEDH."COMMODITYID" = COMMODITIES."COMMODITYID"
AND ((PRODUCEDH."STATUS" IN ('C','X')))
AND PRODUCEDH.COMPLETE_TIME IS NOT NULL
AND COALESCE(PRODUCEDH."COMPLETE_TIME",PRODUCEDH."CREATETIME")+CAST('30.12.1899'AS TIMESTAMP) >= '05-01-2018'
AND COALESCE(PRODUCEDH."COMPLETE_TIME",PRODUCEDH."CREATETIME")+CAST('30.12.1899'AS TIMESTAMP) <= '06-13-2018'
GROUP BY
DateCompleted,
TimeCompleted,
COMMODITIES.code,
COMMODITIES.NAME
ORDER BY
DateCompleted,
TimeCompleted
ASC
) x
LEFT JOIN x others ON others.DateCompleted > x.DateCompleted <------ Error points here
GROUP BY x.DateCompleted, x.TimeCompleted
ORDER BY "dense_rank"
我不知道我做错了什么,但它无法选择表“X”并抛出错误,即SQL错误代码= -204表未知X
最佳答案
最好的解决方案是升级到 Firebird 3,因为它内置了对 window functions like DENSE_RANK()
的支持。 .
无论如何,查询的问题在于您无法基于联接左侧的子查询定义表x
,然后使用该 >x
也在右手。相反,您需要使用 Common Table Expression ,在 Firebird 2.1 中引入:
WITH x AS (
SELECT floor(PRODUCEDH.COMPLETE_TIME)+cast('30.12.1899' AS TIMESTAMP) AS DateCompleted,
(ABS(PRODUCEDH.COMPLETE_TIME) - FLOOR(ABS(PRODUCEDH.COMPLETE_TIME)))+cast('30.12.1899' AS TIMESTAMP) AS TimeCompleted,
COMMODITIES.CODE,
COMMODITIES.NAME AS COMMODITY_NAME,
(SUM(PRODUCEDH.MIXSIZE) / 100) as numOfBatches
FROM
"PRODUCEDH" "PRODUCEDH",
"COMMODITIES" "COMMODITIES"
WHERE
PRODUCEDH."COMMODITYID" = COMMODITIES."COMMODITYID"
AND ((PRODUCEDH."STATUS" IN ('C','X')))
AND PRODUCEDH.COMPLETE_TIME IS NOT NULL
AND COALESCE(PRODUCEDH."COMPLETE_TIME",PRODUCEDH."CREATETIME")+CAST('30.12.1899'AS TIMESTAMP) >= '05-01-2018'
AND COALESCE(PRODUCEDH."COMPLETE_TIME",PRODUCEDH."CREATETIME")+CAST('30.12.1899'AS TIMESTAMP) <= '06-13-2018'
GROUP BY
DateCompleted,
TimeCompleted,
COMMODITIES.code,
COMMODITIES.NAME
ORDER BY
DateCompleted,
TimeCompleted
ASC
)
SELECT x.DateCompleted, x.TimeCompleted, x.numOfBatches, COUNT(DISTINCT others.DateCompleted) + 1 AS "dense_rank"
FROM x
LEFT JOIN x others ON others.DateCompleted > x.DateCompleted
GROUP BY x.DateCompleted, x.TimeCompleted
ORDER BY "dense_rank"
警告一句:我还没有检查这个解决方案本身是否正确;它只是解决了尝试引用 x
两次的问题。
关于sql - 使用子查询模拟 ROW_NUMBER、RANK 和 DENSE_RANK,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50856695/