在DB2SQL中,如何返回只有FETCH FIRST(n)行的可变行数。。?

在DB2SQL中,如何返回只有FETCH FIRST(n)行的可变行数。。?,db2,db2-400,Db2,Db2 400,在DB2 SQL中,如何返回一个n行数可变的行,并只获取前n行。。?这是针对DB2/400V7R3的 这份报告确实明确指出这是不可能的,但我无法想象另一种方式来做到这一点 …获取行计数不能包含标量fullselect、列引用、表引用、用户定义函数引用或内置标量函数 …我认为这意味着它必须是一个常量,如10,不能是变量或列名,不幸的是,这正是我想要做的 这项工作: SELECT PREFILTER.* FROM PREFILTER INNER JOIN GT1 ON FI

在DB2 SQL中,如何返回一个n行数可变的行,并只获取前n行。。?这是针对DB2/400V7R3的

这份报告确实明确指出这是不可能的,但我无法想象另一种方式来做到这一点

…获取行计数不能包含标量fullselect、列引用、表引用、用户定义函数引用或内置标量函数

…我认为这意味着它必须是一个常量,如10,不能是变量或列名,不幸的是,这正是我想要做的

这项工作:

SELECT      PREFILTER.*
FROM        PREFILTER
INNER JOIN  GT1 ON FILTERED.GTAMT=GT1.LOSTAMT
ORDER BY    GTDATE DESC
FETCH FIRST 10 ROWS ONLY
这不起作用:

SELECT      PREFILTER.*
FROM        PREFILTER
INNER JOIN  GT1 ON PREFILTER.GTAMT=GT1.LOSTAMT
ORDER BY    GTDATE DESC
FETCH FIRST (GT1.LOSTAMT) ROWS ONLY    <=== changed here
此查询的目的是在一个较大的表中查找孤立或键入错误的金融交易记录,该表具有相当松散的规范化和引用完整性,或者缺少规范化和引用完整性

PREFILTER是一个返回主表子集的查询,而GT1是另一个计算这些记录的更小更复杂子集的查询。然后将它们连接起来,并按照LOSTQTY列指定的日期降序返回n行。因此,它应该只返回n条最近的记录

请注意,我确实认识到FETCH的位置是不正确的,它或它变形为的任何东西可能必须移动到一个CTE查询中,例如GT1

此外,在这个早期阶段,我似乎得到了一些笛卡尔结果,但一旦FETCH问题得到解决,这可能会得到解决

以下是该项目的完整SQL供参考:

WITH  --SET THE INITIAL ACCOUNT & DATE RANGE  
        PREFILTER    AS  (   SELECT      *
                            FROM        GLTRANT
                            WHERE       GTDATE > 20170000
                            AND         GTACCT=112068
                        ),
      --CREATE LIST OF ALL POSITIVE VALUES
        POSVALS     AS  (   SELECT      GTAMT      AS POSAMT, COUNT(GTAMT) AS POSC
                            FROM        PREFILTER 
                            WHERE       GTAMT > 0
                            GROUP BY    GTAMT
                        ),
      --CREATE LIST OF ALL NEGATIVE VALUES, WITH SIGN DROPPED
        NEGVALS     AS  (   SELECT      ABS(GTAMT) AS NEGAMT, COUNT(GTAMT) AS NEGC
                            FROM        PREFILTER 
                            WHERE       GTAMT < 0
                            GROUP BY    ABS(GTAMT)
                        ),
      --CALCULATE DISCREPANCIES BETWEEN THE TWO LISTS. SUBTRACT THE TWO AND MULTIPLY THE SIGN BY THE ABSOLUTE VALUE 
      --OF THE DIFFERENCE. THEN TO RESTORE THE SIGN, MULTIPLY THE AMOUNT BY THE SIGN OF THE DIFFERENCE. 
        FOJ         AS  (   SELECT      SIGN(COALESCE(POSC,0)-COALESCE(NEGC,0))*COALESCE(POSAMT,NEGAMT) AS LOSTAMT, 
                                        ABS (COALESCE(POSC,0)-COALESCE(NEGC,0))                         AS LOSTQTY
                            FROM        POSVALS 
                            FULL OUTER JOIN NEGVALS ON POSAMT=NEGAMT
                            WHERE       COALESCE(POSC,0)-COALESCE(NEGC,0) <> 0
                        ),
      --GET DISCREPANCIES WITH COUNT >1 
        GT1         AS  (   SELECT      *
                            FROM        FOJ
                            WHERE       LOSTQTY>1 
                        )

--SEARCH PREFILTER FOR EACH AMOUNT (LOSTAMT) IN GT1 AND RETURN THE MOST RECENT (LOSTQTY) RECORDS 
SELECT      PREFILTER.*
FROM        PREFILTER
INNER JOIN  GT1 ON PREFILTER.GTAMT=GT1.LOSTAMT
ORDER BY    GTDATE DESC
FETCH FIRST (GT1.LOSTQTY) ROWS ONLY --DOES NOT WORK

我不确定你能在一份声明中做你想做的事。但是,您应该能够组合一个存储过程或SQL函数来代替它。在存储过程中,将查询放在一起,然后用光标打开它。然后,游标可以获取所需的行数,将其放入结果集中,并从过程返回该结果集。IBM关于这方面的最新文档如下:

我不确定您是否可以在一条语句中完成您想要的任务。但是,您应该能够组合一个存储过程或SQL函数来代替它。在存储过程中,将查询放在一起,然后用光标打开它。然后,游标可以获取所需的行数,将其放入结果集中,并从过程返回该结果集。IBM的最新文档如下所示:

您应该能够使用:

WITH  --SET THE INITIAL ACCOUNT & DATE RANGE  
        PREFILTER    AS  (  
          SELECT  T.*,
                  ROW_NUMBER() OVER (ORDER BY T.GTDATE DESC) AS RN
          FROM (
                            SELECT      *
                            FROM        GLTRANT
                            WHERE       GTDATE > 20170000
                            AND         GTACCT=112068
          ) T
        ),
...
--SEARCH PREFILTER FOR EACH AMOUNT (LOSTAMT) IN GT1 AND RETURN THE MOST RECENT (LOSTQTY) RECORDS 
SELECT      PREFILTER.*
FROM        PREFILTER
INNER JOIN  GT1 ON PREFILTER.GTAMT=GT1.LOSTAMT
WHERE RN <= GT1.LOSTQTY
ORDER BY    GTDATE DESC

它按GTDATE的降序为PREFILTER中的每一行分配连续的数字,您可以稍后使用该数字来限制结果集。

您应该能够使用a来实现此目的:

WITH  --SET THE INITIAL ACCOUNT & DATE RANGE  
        PREFILTER    AS  (  
          SELECT  T.*,
                  ROW_NUMBER() OVER (ORDER BY T.GTDATE DESC) AS RN
          FROM (
                            SELECT      *
                            FROM        GLTRANT
                            WHERE       GTDATE > 20170000
                            AND         GTACCT=112068
          ) T
        ),
...
--SEARCH PREFILTER FOR EACH AMOUNT (LOSTAMT) IN GT1 AND RETURN THE MOST RECENT (LOSTQTY) RECORDS 
SELECT      PREFILTER.*
FROM        PREFILTER
INNER JOIN  GT1 ON PREFILTER.GTAMT=GT1.LOSTAMT
WHERE RN <= GT1.LOSTQTY
ORDER BY    GTDATE DESC
它按照GTDATE的降序为PREFILTER中的每一行分配连续的数字,您可以稍后使用这些数字来限制结果集。

好的,在吸收了前面的答案并在IBM文档上花了一整天的时间之后,我能够解决这个问题。非常感谢你为我指明了正确的方向

两个重要的位:行号的位置必须进一步向下移动;它在这里不起作用。此外,它还需要添加PARTITION BY参数,以便使用每个新的值组重新开始编号。所以它是1-2-1-2-1-2-3而不是1-2-3-4-5-6-7。这对于RNOk来说是至关重要的,在吸收了之前的答案并在IBM文档上花了一整天的时间之后,我能够解决这个问题。非常感谢你为我指明了正确的方向


两个重要的位:行号的位置必须进一步向下移动;它在这里不起作用。此外,它还需要添加PARTITION BY参数,以便使用每个新的值组重新开始编号。所以它是1-2-1-2-1-2-3而不是1-2-3-4-5-6-7。这对于引用页面确实指出不能使用列引用作为要返回的行数的表达式是至关重要的

它允许的是一个表达式。有一些规则说明什么是不允许的,但这些规则并不排除使用宿主变量

    FETCH FIRST :xqty ROWS ONLY

引用页面确实指出,您不能像试图做的那样使用列引用作为要返回的行数的表达式

它允许的是一个表达式。有一些规则说明什么是不允许的,但这些规则并不排除使用宿主变量

    FETCH FIRST :xqty ROWS ONLY

GT1.LOSTAMT应该是GT1.LOSTQTY吗?啊,是的,好眼力。当我复制粘贴并替换10时,我粘贴了错误的一个。GT1.LOSTAMT应该是GT1.LOSTQTY吗?啊,是的,好眼力。当我复制粘贴并替换了10个时,我粘贴了错误的一个。在过去,我一直在努力解决这个问题,这是我遇到的最好的解决方案。是的,哇,这似乎是有效的。太棒了但为什么要选择子选项。。?为什么不像这样简单地把它和OLAP&so结合起来呢
rt是否在同一选择状态?在预过滤器为SELECT GLTRANT.*的情况下,F_CERTOB.GLTRANT中RN上的行数,其中GTDATE>20180000且GTACCT=112068按GTDATE DESC排序对不起,上面有轻微错误。我重新阅读了你链接的帮助文本,意识到我把订单放错了地方。假设无需子选择即可完成此操作,则这应该是正确的:使用PREFILTER作为SELECT GLTRANT.*,通过F_CERTOB.GLTRANT中的GTDATE DESC RN按订单的行数,其中GTDATE>20180000且GTACCT=112068,您当然可以将其合并在一起,我只是想强调行数的使用。在过去,我一直在努力解决这个问题,这是我遇到的最好的解决方案。是的,哇,这似乎奏效了。太棒了但为什么要选择子选项。。?为什么不像这样简单地把它放在一起,把OLAP和sort放在同一个select语句中?在预过滤器为SELECT GLTRANT.*的情况下,F_CERTOB.GLTRANT中RN上的行数,其中GTDATE>20180000且GTACCT=112068按GTDATE DESC排序对不起,上面有轻微错误。我重新阅读了你链接的帮助文本,意识到我把订单放错了地方。假设无需子选择即可完成此操作,则这应该是正确的:使用PREFILTER作为SELECT GLTRANT.*,通过F_CERTOB.GLTRANT中的GTDATE DESC RN按订单的行数,其中GTDATE>20180000且GTACCT=112068,您当然可以将其合并在一起,我只是想强调行号的使用。您能在IBM网站或其他地方给我一些关于这方面的文档吗。。?我在谷歌上搜索了一下,但得到的搜索结果很大,但信息量不大;IBM的网站非常庞大,人们经常聊天=-使用主机变量意味着您正在使用另一种语言使用嵌入式SQL将变量就地注入:即使用C、RPGLE或COBOL等。从这个问题判断,我认为您需要的是纯SQL解决方案。不知何故,请不要问我为什么我认为您可能会使用这些语言中的一种进行此操作。我想可以用一个SQL过程变量来实现这一点。但如果我没有提出,我也会用同样的解决方案来回应。他通常是恰到好处的;您能在IBM网站或其他地方给我一些关于这方面的文档吗。。?我在谷歌上搜索了一下,但得到的搜索结果很大,但信息量不大;IBM的网站非常庞大,人们经常聊天=-使用主机变量意味着您正在使用另一种语言使用嵌入式SQL将变量就地注入:即使用C、RPGLE或COBOL等。从这个问题判断,我认为您需要的是纯SQL解决方案。不知何故,请不要问我为什么我认为您可能会使用这些语言中的一种进行此操作。我想可以用一个SQL过程变量来实现这一点。但如果我没有提出,我也会用同样的解决方案来回应。他通常是恰到好处的;