我有一个多次调用的报告,但我希望每次订单都不同。
如何根据变量更改“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
但它没有用......还有其他建议吗? 谢谢!
答案 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代码编译器,你应该看看为报告生成的代码,但要注意它是你可能遇到的最可怕的代码在很长的时间。它使用了你不会梦想自己使用的各种技巧。
行;所以你可以直接做到。你有什么选择?在我看来,你有两个选择:
使用两个参数专门用于选择排序,然后使用ORDER BY(没有EXTERNAL
)子句,它始终按固定顺序列出它们。但是,当需要使用报告时,请选择您想要参数的序列。
编写两个报告,这些报告仅在报告名称和ORDER EXTERNAL BY子句中有所不同。根据您想要的顺序安排调用正确的报告。
其中,选项2到目前为止更简单 - 除了维护问题。最有可能的是,您安排从单个副本生成代码。也就是说,您将REPORT print_label_code_desc
保存在一个文件中,然后安排将其编辑为REPORT print_label_desc_code
(例如,使用sed
) - 编辑将颠倒顺序ORDER BY子句中的名称。这在makefile
中并不难做到,尽管需要一些小心。
选项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足够长的整个文本。