使用子查询模拟ROW_NUMBER,RANK和DENSE_RANK

时间:2018-06-14 11:38:30

标签: sql firebird self-join firebird2.5

我想在我的一个JasperReport查询中使用1 finalAction) at Abp.Threading.InternalAsyncHelper.AwaitTaskWithFinallyAndGetResult[T](Task函数,但它不适用于Firebird 2.5。但是有一个example on the firebirdfaq.org site来使用聚合函数和上下文变量或生成器来模拟这个函数。即

DENSE_RANK()

所以它是玩家的自我加入。

我的问题是我没有像“玩家”那样的定义表格。自己加入它但我的查询使用两个表。我尝试创建一个别名并使用子查询自行加入但没有成功。

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"

我不知道自己做错了什么,但却未能在桌面上挑选&#34; X&#34;并抛出一个错误,即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"

1 个答案:

答案 0 :(得分:3)

最好的解决方案是升级到Firebird 3,就像内置对Object.assign的支持一样。

在任何情况下,查询的问题在于您无法根据联接左侧的子查询定义表x,然后使用x在右边。相反,您需要使用window functions like DENSE_RANK(),它在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两次的问题。