Sql 使用子查询模拟行数、秩和稠密秩

Sql 使用子查询模拟行数、秩和稠密秩,sql,firebird,self-join,firebird2.5,Sql,Firebird,Self Join,Firebird2.5,我想在我的一个JasperReport查询中使用densite\u RANK()函数,但Firebird 2.5不提供该函数。但是,使用聚合函数和上下文变量或生成器来模拟此函数是一种非常困难的方法。i、 e 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 GROU

我想在我的一个JasperReport查询中使用
densite\u RANK()
函数,但Firebird 2.5不提供该函数。但是,使用聚合函数和上下文变量或生成器来模拟此函数是一种非常困难的方法。i、 e

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"
因此,这是一个自我加入的球员

我的问题是,我没有一个像“players”这样的定义表来进行自连接,但我的查询使用了两个表。我尝试创建一个别名并使用子查询进行自联接,但没有成功

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.DateCompleted、x.TimeCompleted、x.numOfBatches、COUNT(不同的其他.DateCompleted)+1作为“密集等级”
从…起
(选择楼层(生产完成时间)+演员阵容('30.12.1899'作为时间戳)作为日期完成,
(ABS(生产完成时间)-地板(ABS(生产完成时间))+cast('30.12.1899'作为时间戳)作为时间完成,
商品代码,
商品名称作为商品名称,
(总和(生产混合尺寸)/100)为个批次
从…起
“PRODUCEDH”“PRODUCEDH”,
“商品”“商品”
哪里
PRODUCEDH。“商品ID”=商品。“商品ID”
和(('C','X')中的PRODUCEDH.“STATUS”)
和PRODUCEDH.COMPLETE_TIME不为空
和联合(PRODUCEDH.“完成时间”,PRODUCEDH.“创建时间”)+CAST('30.12.1899'作为时间戳)>='05-01-2018'

和COALESCE(PRODUCEDH.“COMPLETE_TIME”,PRODUCEDH.“CREATETIME”)+CAST('30.12.1899'作为时间戳)x.DateCompleted最好的解决方案是升级到Firebird 3,因为它是对的内置支持

在任何情况下,查询的问题在于,您不能基于联接左侧的子查询定义表
x
,然后在右侧使用该
x
。相反,您需要使用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作为(
选择floor(生产完成时间)+cast(时间戳为1899年12月30日)作为DateCompleted,
(ABS(生产完成时间)-地板(ABS(生产完成时间))+cast('30.12.1899'作为时间戳)作为时间完成,
商品代码,
商品名称作为商品名称,
(总和(生产混合尺寸)/100)为个批次
从…起
“PRODUCEDH”“PRODUCEDH”,
“商品”“商品”
哪里
PRODUCEDH。“商品ID”=商品。“商品ID”
和(('C','X')中的PRODUCEDH.“STATUS”)
和PRODUCEDH.COMPLETE_TIME不为空
和联合(PRODUCEDH.“完成时间”,PRODUCEDH.“创建时间”)+CAST('30.12.1899'作为时间戳)>='05-01-2018'
合并(PRODUCEDH.“完成时间”,PRODUCEDH.“创建时间”)+CAST('30.12.1899'作为时间戳)x.DateCompleted
按x.DateCompleted、x.TimeCompleted分组
按“密集等级”排序

警告一句:我还没有检查这个解决方案本身是否正确;它只是解决了尝试引用
x
两次的问题。

我认为您必须在Firebird中重复子查询。在大多数SQL方言中,您会使用公共表表达式(CTE),但我认为Firebird不支持它们。没有任何“官方”选项关于FiffBidFaq.Org,这些官方的实现是FielBube 3,它增加了支持,考虑升级。@ GordonLinoff FielBube支持通用表表达式,参见FieldBee 2.5语言reference@GordonLinoff它可以像u建议的那样重复子查询,但是需要花费相当长的时间才能完成执行如果我的查询需要0.311秒,如果我模拟它大约需要3分钟。如果我能让它快速运行,有没有可能?谢谢马克,我也尝试过你的解决方案,但效果很好,但执行时间很紧。对于设置条件,如果查询本身需要0.311秒,通过模拟此函数大约需要3分钟。我是否可以选择模拟执行?我知道最好升级到firebird 3,但我现在不可能。@AlphaTry我不能马上想到一些东西。这只是因为自连接而不是很有效。