在INFORMIX 4GL的报告中的“ORDER BY”上使用“IF语句”

时间:2016-09-07 18:39:05

标签: informix 4gl

我有一个多次调用的报告,但我希望每次订单都不同。

如何根据变量更改“order by”。

例如

report print_label()

   If is_reprint
   then
       order by rpt.item_code, rpt.description
   else
       order by rpt.description, rpt.item_code
   end if

我在调用报告时尝试传入一个变量:

let scratch = "rpt.item_code, rpt.description"
start print_label(scratch)

在报告中我做了:

order by scratch

但它没有用......还有其他建议吗? 谢谢!

4 个答案:

答案 0 :(得分:2)

我用于此类问题的技术是

之类的
REPORT report_name(x)
DEFINE x RECORD
    param1,param2, ..., paramN ...,
    sort_method ...,
    data ...
END RECORD

ORDER [EXTERNAL] BY x.param1, x.param2, ..., x.paramN

BEFORE GROUP OF x.param1
    CASE 
        WHEN x.sort_method ...
            PRINT ...
        WHEN x.sort_method ...
            PRINT ...
    END CASE

BEFORE GROUP OF x.param2
    # similar technique as above

...

BEFORE GROUP OF x.paramN
    # similar technique as above

ON EVERY ROW
    PRINT ...

AFTER GROUP OF x.paramN
   # similar technique as above
...

AFTER GROUP OF x.param2
    # similar technique as above

AFTER GROUP OF x.param1
    # similar technique as above

...然后在调用REPORT的4gl中,填充x.param1,x.param2,...,x.paramN以及用于排序的所需参数,例如。

CASE x.sort_method 
    WHEN "product,branch"
        LET x.param1 = x.data.product_code
        LET x.param2 = x.data.branch_code
    WHEN "branch,product"
        LET x.param1 = x.data.branch_code
        LET x.param2 = x.data.product_code
END CASE
OUTPUT TO REPORT report_name(x.*)

根据我的例子,这是我见过并用于股票报告之类的技术。仓库/分公司/商店经理想要查看按仓库/分店/商店订购的商品,然后按产品/ sku / item查看,而产品经理想要查看按产品/ sku / item订购的商品,然后仓库/分店/商店。可以使用相同的技术完成更多具有更多潜在参数的分析报告。我认为我所看到的记录是6.所以在这种情况下,1报告覆盖所有6!= 720个潜在组合要好得多,而不是为每个可能的订单组合编写单独的报告。

所以可能类似于Jonathan选项1,尽管我对复杂性没有相同的保留意见。我不记得在任何一个初级开发人员遇到严重错误的代码审查时。事实上,如果报告足够通用,您会发现您不需要经常触摸它。

答案 1 :(得分:1)

简短回答

I4GL REPORT函数中的ORDER BY子句对如何生成实现报告的代码具有至关重要的影响。在运行时将生成的代码重新连接是根本不可行的。

因此,您无法直接获得所需的结果。

注释

请注意,您应该使用ORDER EXTERNAL BY而不是ORDER BY - 区别在于EXTERNAL,报告可以假设数据以正确的顺序显示,但没有,报告必须保存所有数据(在数据库的临时表中),然后按所需的排序顺序从表中选择数据,并将其转换为两遍报告。

如果你勇敢并拥有I4GL c代码编译器,你应该看看为报告生成的代码,但要注意它是你可能遇到的最可怕的代码在很长的时间。它使用了你不会梦想自己使用的各种技巧。

解决方案解决方案 - 概述

行;所以你可以直接做到。你有什么选择?在我看来,你有两个选择:

  1. 使用两个参数专门用于选择排序,然后使用ORDER BY(没有EXTERNAL)子句,它始终按固定顺序列出它们。但是,当需要使用报告时,请选择您想要参数的序列。

  2. 编写两个报告,这些报告仅在报告名称和ORDER EXTERNAL BY子句中有所不同。根据您想要的顺序安排调用正确的报告。

  3. 其中,选项2到目前为止更简单 - 除了维护问题。最有可能的是,您安排从单个副本生成代码。也就是说,您将REPORT print_label_code_desc保存在一个文件中,然后安排将其编辑为REPORT print_label_desc_code(例如,使用sed) - 编辑将颠倒顺序ORDER BY子句中的名称。这在makefile中并不难做到,尽管需要一些小心。

    实践中的选项1

    选项1在实践中看起来像什么?

    DECLARE c CURSOR FOR
        SELECT * FROM SomeTable
    
    START REPORT print_label -- optional specification of destination, etc.
    
    FOREACH c INTO rpt.*
        IF do_item_desc THEN
            OUTPUT TO REPORT print_label(rpt.item_code, rpt.description, rpt.*)
        ELSE
            OUTPUT TO REPORT print_label(rpt.description, rpt.item_code, rpt.*)
        END IF
    END FOREACH
    
    FINISH REPORT print_label
    

    报告功能本身可能如下所示:

    REPORT print_label(col1, col2, rpt)
        DEFINE col1 CHAR(40)
        DEFINE col2 CHAR(40)
        DEFINE rpt  RECORD LIKE SomeTable.*
    
        ORDER BY col1, col2
    
    FORMAT
    
        FIRST PAGE HEADER
            …
        BEFORE GROUP OF col1
            …
        BEFORE GROUP OF col2
            …
        ON EVERY ROW
            …
        AFTER GROUP OF col1
            …
        AFTER GROUP OF col2
            …
        ON LAST ROW
            …
    END REPORT
    

    对大纲代码中的任何错误表示歉意;自从我上次编写任何I4GL代码以来已经有一段时间了。

    关键点在于,按值排序的值是专门传递给报告的,仅用于控制其组织。你可能需要 能够在BGO中打印不同的细节(BEFORE GROUP OF的简写; AFTER GROUP OF的AGO)两个部分。这通常由(喘气)全局变量处理 - 这是I4GL,它们是正常的业务方式。实际上,如果报告驱动程序代码(调用START REPORT,OUTPUT TO REPORT和FINISH REPORT的代码)与报告本身位于同一文件中,它们应该是模块变量而不是全局变量。您需要这样做,因为通常组级别(在BGO和AGO块中)的报告将需要不同的标题或标签,具体取决于您是否在描述之前对代码进行排序,反之亦然。请注意,组聚合的含义会根据ORDER BY子句中的顺序而改变。

    请注意,并非每个报告都有助于此类重新排序。简单地以不同的顺序运行BGO和AGO块不足以使报告输出看起来合理。在这种情况下,您将回到选项2 - 或选项2A,这是写两个单独的报告,不要假装只是ORDER BY子句的重新排序,因为数据的格式需要根据不同而不同在ORDER BY子句中。

    正如您所看到的,这需要一些关心 - 比替代方案(选项2)更加谨慎。如果使用动态SQL创建SELECT语句,则可以安排将正确的ORDER BY子句放入随后准备的字符串中,以便光标以正确的顺序获取数据 - 允许您使用ORDER EXTERNAL BY

    摘要

    如果您是I4GL的新手,请使用选项2.如果您的团队在I4GL方面没有相当的经验,请选择选项2.我不太喜欢它,但这是方式这可以很容易地处理,并且很容易被你自己,你现在的同事以及即将到来的人所理解。

    如果您对I4GL非常熟悉并且您的团队对I4GL有相当的经验 - 并且报告布局真的有助于动态重组 - 那么请考虑选项1.这很棘手,但我已经完成了过去I4GL中的情况更糟。

答案 2 :(得分:0)

您可以在order by子句中使用case语句,如下所示:

order by 
       case 
         when 1 = 1 then 
            rpt.item_code, rpt.description
         else
            rpt.description, rpt.item_code
       end

答案 3 :(得分:0)

您可以使用prepare:

let query_txt="select ... "
If is_reprint then
  let query_txt=query_txt clipped, " order by rpt.item_code, 
  rpt.description"
else
  let query_txt=query_txt clipped, " order by rpt.description, 
  rpt.item_code"
end if
prepare statement1 from query_txt
declare cursor_name cursor for statement1

现在开始报告,使用foreach等等......

P.S。您必须将query_txt定义为char足够长的整个文本。