Ibm midrange 如何在给定条件下为字段选择最高值?

Ibm midrange 如何在给定条件下为字段选择最高值?,ibm-midrange,rpgle,rpg,Ibm Midrange,Rpgle,Rpg,我正在使用考勤系统,其中我的物理文件(PF)包含以下字段: User ID(key field),Date,Time In,Time Out ...... 问题是,我试图为特定的用户ID和日期以及当天的最高超时值选择。并将超时值移动到程序中的变量 如何创建RPGLE源代码?传统的方法是构建一个逻辑文件,其中用户ID、日期和超时作为键,日期和超时按降序排列。然后,我认为只要使用用户ID和今天的日期作为部分键链接到逻辑,就可以得到最新的记录。嵌入式SQL也可以: SELECT MAX(timeou

我正在使用考勤系统,其中我的物理文件(PF)包含以下字段:

User ID(key field),Date,Time In,Time Out
......
问题是,我试图为特定的用户ID和日期以及当天的最高超时值选择。并将超时值移动到程序中的变量


如何创建RPGLE源代码?

传统的方法是构建一个逻辑文件,其中用户ID、日期和超时作为键,日期和超时按降序排列。然后,我认为只要使用用户ID和今天的日期作为部分键链接到逻辑,就可以得到最新的记录。

嵌入式SQL也可以:

SELECT MAX(timeout) 
INTO :outTime  
FROM PF 
WHERE userid = :selected_user_id
AND date = :selected_date`

假设您有一个员工文件和一个时间工作文件,如您所述。您需要报告每个员工在给定日期的最早入职时间和最新超时时间

因此,您可能有一个读取员工文件的循环,在该循环中,您可以链接到@Martin描述的逻辑,以获取最后一个超时,另一个逻辑键入升序时间,以获取最小值

使用SQL,您可以在一次读取中获取员工文件信息,以及最早的输入时间和最新的超时时间(在SQL中获取)。它大大简化了循环中的代码,不是吗

下面是伪代码的基本流程:

Declare a cursor with your SQL statement
Open the cursor
Fetch a row from the cursor
DoWhile status is ok
    Process your data
    Fetch the next record
EndDo
Close the cursor
看起来不太吓人吧?让我们看看代码可能是什么样子。当然,在SQL中有不止一种方法,但让我们从简单的SQL Select语句开始。在SQL中使用RPG变量时,可以使用冒号(“:”)作为前缀

好吧,这是一个很有选择的说法,嗯?发生了很多事

但它分为两部分。第一部分是一个名为h的表表达式,我们从中获取每个员工在该日期的时间。第二部分列出了我们需要的所有结果字段,这些字段取自表表达式h和employees文件,只要我们可以匹配这两个文件中的员工编号。这些行将按姓、名和员工编号排序

让我们把这个放到RPG里

EXEC-SQL  DECLARE CURSOR C1 AS
              WITH h as
              ( SELECT empID, min(timein) as firstin, max(timeout) as lastout
                  FROM workhours
                  WHERE workdate = :myvariable
                  GROUP BY empID
              )
              SELECT e.lastname, e.firstname, e.empnbr, h.firstin, h.lastout
                FROM h
                JOIN employees as e   on h.empID = e.empnbr
                ORDER BY e.lastname, e.firstname, e.empnbr
                FOR READ ONLY;
EXEC-SQL  OPEN C1;
EXEC-SQL  FETCH FROM C1
            INTO :lname, :fname, :emp, :firsttime, :lasttime;
DoW &subst(SQLState,1,2) = '00';
    //
    // perform processing here
    //
    EXEC-SQL  FETCH FROM C1
                INTO :lname, :fname, :emp, :firsttime, :lasttime;
enddo;
EXEC-SQL  CLOSE C1;

现在,您可能首先会对游标中的SELECT语句完成了多少工作感到犹豫。但是,通过所有这些操作,您简化了I/O,并让SQL优化器发挥其魔力,找到最快的方式将数据发送给您。

如果日期和时间字段属于同一个字段,请不要将它们分开。除非您的空间受到严重限制,否则节省的空间不值得处理它(主要是在使用SQL时——您应该这样做)。是的,您最好使用嵌入式SQL,如下面的@Buck所示。理解这些概念可能需要花费更多的努力,但它会带来丰厚的回报,并且可以导致设计更简单、编写和运行更快。不能使用嵌入式SQL..任何其他建议按个人偏好从最差到最差排序:阅读每一条记录并自己跟踪这些值,FMTDTA,OPNQRYF都是SQL的替代品。谢谢……还有一个愚蠢的问题要问……我可以将另一个字段声明为键字段吗?。即使在我的PF中,我也只将USRID声明为键字段。?……键字段应该是同一类型的吗(因为我在使用Chain时发现另一个字段的错误不是同一类型的)?…RPG程序中的键字段必须与文件中的键字段匹配。如果您需要一个额外的密钥字段,请用所需的密钥创建一个逻辑文件,并在RPG程序中使用。@BuckCalabro,您所写的语句不正确。例如,文件可以按用户、日期和输入(或输出)时间键入。。。程序可能只引用用户作为密钥。那很好。我认为您的意思是,您的程序不能引用为键,文件中未定义为键的内容。需要使用其他键重新创建文件(注意!数据丢失!),或者可以使用ALTER TABLE添加约束。或者,正如你所建议的,可能会创建一个新的逻辑。@Dennis,完全同意你的观点。如果你不能使用嵌入式SQL,那么Martin的答案可能是个不错的选择。但是,如果您希望使用SQL选项,那么可以将SELECT语句放入QM查询中,并将输出发送到文件。QM查询为您提供了指定变量的能力,方法是在名称前面加上与CL中相同的符号和。STRQMQRY命令允许您传入变量的值。因此,您可以说
STRQMQRY myqry OUTPUT(*FILE)OUTFILE(qtemp/results)SETVAR((&MYVARIABLE''2012-07-14'))
EXEC-SQL  DECLARE CURSOR C1 AS
              WITH h as
              ( SELECT empID, min(timein) as firstin, max(timeout) as lastout
                  FROM workhours
                  WHERE workdate = :myvariable
                  GROUP BY empID
              )
              SELECT e.lastname, e.firstname, e.empnbr, h.firstin, h.lastout
                FROM h
                JOIN employees as e   on h.empID = e.empnbr
                ORDER BY e.lastname, e.firstname, e.empnbr
                FOR READ ONLY;
EXEC-SQL  OPEN C1;
EXEC-SQL  FETCH FROM C1
            INTO :lname, :fname, :emp, :firsttime, :lasttime;
DoW &subst(SQLState,1,2) = '00';
    //
    // perform processing here
    //
    EXEC-SQL  FETCH FROM C1
                INTO :lname, :fname, :emp, :firsttime, :lasttime;
enddo;
EXEC-SQL  CLOSE C1;