LSELECT
It is easy to select data from a file when a field equals a known value. e.g.
>LIST CUSTOMER WITH CUSTNO = "12345"
It is also easy to select data from a file when a field equals one of a number of known value. e.g.
>LIST CUSTOMER WITH CUSTNO = "12345""12346""12347""12348"
The query processor is very powerful and offers many ways to easily accommodate queries. Using selects before processing a query is a standard method to filter data. e.g.
>SELECT CUSTOMER WITH CUSTTYPE = "1"
14 items selected.
>>SELECT CUSTOMER WITH CUSTNO = "12345"
3 items selected.
>>LIST CUSTOMER
On occasion, we have a list of data we'd like to compare a select to to see if any data exists in the list. We might have a list of non-primary key values of colors and we want to select the items in a product file whose color matches one of the colors in this list.
It would be a very nice feature if we could do something like:
>LSELECT PRODUCTS WITH COLOR IN MYLIST
Somewhere we created MYLIST based on various colors with certain properties. e.g.
>SELECT COLORS WITH COLORTYPE = "POPULAR"
20 items selected.
>SAVE.LIST MYLIST Overwriting existing saved list. 20 key(s) saved to 1 record(s).
Now we want to use our fantasized query to select all our products that have this popular color.
>LSELECT PRODUCTS WITH COLOR IN MYLIST 750 items selected.
>>SORT PRODUCTS ....
Rocket Software, and IBM before this, had a tech tip that allowed us to create this new verb (LSELECT).
https://u2devzone.rocketsoftware.com/accelerate/articles/u2-select/u2-select
The following is a basic program I created to use on UniData.
! ** Select file items using keys in select list ** (C) Copyright 1985-2012, Pacific Mgmt Software, Inc. All Rights Reserved. ! ** Last Modified: 07 Aug 2012, wph ** First Created: 01 Oct 2009, wph ** Program Type-: Utility ! ** Notes: ** ** This process selects the items in [[FileName]] whose keys are in the ** defined select (saved) list. ** **----------------------------------------------------------------------** ** ** ** I N I T I A L I Z A T I O N ** ** ** **----------------------------------------------------------------------** * ** Initialization NULL$ = '' SP1 = ' ' * * Initialize command variables FILE.NAME = NULL$ DICT.NAME = NULL$ OPER = NULL$ SOURCE.LIST = NULL$ TO.OP = NULL$ DEST.LIST = NULL$ * ** Initialize other variables SOURCE.LIST.NAMED = 1 DEST.LIST.NAMED = 1 DISPLAY.HELP = 0 VERBOSE = 0 * **----------------------------------------------------------------------** ** ** ** S T A R T P R O C E S S I N G D A T A ** ** ** **----------------------------------------------------------------------** * ** Run the command program GOSUB GET.COMMAND GOSUB GET.SOURCE.SELECT.LIST GOSUB CREATE.TEMP.FILE GOSUB LOAD.TEMP.FILE GOSUB BUILD.LIST2 GOSUB FINISH.UP GOTO END.OF.PROGRAM * **----------------------------------------------------------------------** ** ** ** S U B R O U T I N E ( S ) ** ** ** **----------------------------------------------------------------------** * ** Get the command and process *************** GET.COMMAND: *************** * ** Gather and parse input from command line INPUT.PARAMS = TRIM(FIELD(@SENTENCE, " ", 2, 999)) SWAP ' ' WITH ';' IN INPUT.PARAMS POS = 1 FILE.NAME = TRIM(FIELD(INPUT.PARAMS, ";", POS)) POS += 1 WITH.OP = UPCASE(TRIM(FIELD(INPUT.PARAMS, ";", POS))) IF WITH.OP = "WITH" THEN POS += 1 DICT.NAME = TRIM(FIELD(INPUT.PARAMS, ";", POS)) POS += 1 OPER = UPCASE(TRIM(FIELD(INPUT.PARAMS, ";", POS))) IF OPER = "IN" THEN POS += 1 SOURCE.LIST= TRIM(FIELD(INPUT.PARAMS, ";", POS)) POS += 1 TO.OP = UPCASE(TRIM(FIELD(INPUT.PARAMS, ";", POS))) IF TO.OP = "TO" THEN POS += 1 DEST.LIST = TRIM(FIELD(INPUT.PARAMS, ";", POS)) IF DEST.LIST = "VERBOSE" OR DEST.LIST = "-V" THEN VERBOSE = 1 DEST.LIST = NULL$ END END ELSE IF OPER = "TO" THEN POS += 1 DEST.LIST = OCONV(TRIM(FIELD(INPUT.PARAMS, ";", POS)), 'MCU') IF DEST.LIST = "VERBOSE" OR DEST.LIST = "-V" THEN VERBOSE = 1 DEST.LIST = NULL$ END END ELSE IF OPER # NULL$ THEN ERROR.MSG = 'Expecting "IN" or "TO" clause. Found ':OPER GOSUB SHOW.MESSAGE DISPLAY.HELP = 1 END END END * LAST.COMMAND = UPCASE(FIELD(INPUT.PARAMS, ";", DCOUNT(INPUT.PARAMS, ";"))) IF (LAST.COMMAND = "VERBOSE") OR (LAST.COMMAND = "-V") THEN VERBOSE = 1 * ** Display Usage if parameters not supplied or help is requested IF FILE.NAME = NULL$ OR FILE.NAME = "?" OR FILE.NAME = "HELP" OR DICT.NAME = NULL$ THEN DISPLAY.HELP = 1 IF DISPLAY.HELP THEN PRINT PRINT 'This will create a list of {[[FileName]]} keys for records whose' PRINT 'field definition value appears in a defined list.' PRINT PRINT 'Syntax:' PRINT ' LSELECT [[File_Name]] WITH [[Dict_Name]] IN LIST1 TO LIST2 [VERBOSE| -V]' PRINT PRINT 'Example: SELECT CUSTOMERS SAMPLE 500' PRINT ' SAVE.LIST MY.LIST' PRINT ' LSELECT SALES.ORDERS WITH CUST.NBR IN MY.LIST TO MY.LIST.2' PRINT PRINT 'Notes:' PRINT 'If a destination list is not supplied then keys will be left as the active' PRINT 'select list. If a source list is not supplied then the current active select' PRINT 'list will be used. Lists may be specified as select buffers (0-8) or as named' PRINT 'lists from SAVEDLISTS.' PRINT STOP END * ** Validate Dictionary DR.REC = XLATE("DICT ":FILE.NAME, DICT.NAME, -1, "X") IF DR.REC = NULL$ THEN ERROR.MSG = "Unable to read dictionary ":DICT.NAME:" for file ":FILE.NAME GOSUB SHOW.MESSAGE STOP END ELSE IF DR.REC<6> # "S" THEN ERROR.MSG = "Warning, ":DICT.NAME:" is not a single valued field. Results may be unexpected." GOSUB SHOW.MESSAGE END END * ** Complete defaulting behavior IF SOURCE.LIST = NULL$ THEN SOURCE.LIST = 0 END * ** Make sure the destination list has a value IF DEST.LIST = NULL$ THEN DEST.LIST = 0 * ** Make sure source list name has a value (under misc circumstances) IF NUM(SOURCE.LIST) AND LEN(SOURCE.LIST) = 1 AND (SOURCE.LIST NE 9) THEN SOURCE.LIST.NAMED = 0 * ** Make sure destination list name has a value (under misc circumstances) IF NUM(DEST.LIST) AND LEN(DEST.LIST)=1 AND (DEST.LIST # 9) THEN DEST.LIST.NAMED = 0 * ** Display verbose information IF VERBOSE THEN PRINT '(Parsed Command)' PRINT 'LSELECT ':FILE.NAME:' WITH ':DICT.NAME:' IN ':SOURCE.LIST:' TO ':DEST.LIST PRINT END RETURN ! ** Get the list of values to match *************** GET.SOURCE.SELECT.LIST: *************** * SOURCE.ID.LIST = NULL$ * ** Process a named list IF SOURCE.LIST.NAMED THEN EXECUTE \GET-LIST \ : SOURCE.LIST CAPTURING OUTPUT [[NoOfItems]] = SYSTEM(11) IF NOT([[NoOfItems]]) THEN ERROR.MSG = "Error reading saved list ":SOURCE.LIST : SP1 : OUTPUT GOSUB SHOW.MESSAGE STOP END READSELECT SOURCE.ID.LIST ELSE SOURCE.ID.LIST = NULL$ END ELSE READSELECT SOURCE.ID.LIST FROM SOURCE.LIST ELSE SOURCE.ID.LIST = NULL$ END * ** Display verbose information IF VERBOSE THEN PRINT '(Selected List)' PRINT 'List Source ':SOURCE.LIST:' found ':DCOUNT(SOURCE.ID.LIST, @AM):' items.' PRINT END RETURN ! ** Create temporary file to support TRANS selection *************** CREATE.TEMP.FILE: *************** * ** determine appropriate file size based on size of list of values to match TBYTES = SUM(LENS(SOURCE.ID.LIST)) TEMP.MOD = INT(TBYTES/1024) IF TEMP.MOD < 1 THEN TEMP.MOD = 5 END PROCESS.NBR = @UDTNO + 0 PROCESS.ID = ('0000' : PROCESS.NBR : @LEVEL) "R#4" TEMP.NAME = 'LSELECT' : PROCESS.ID UDT.COMMAND = 'CREATE.FILE ' : TEMP.NAME : SP1 : TEMP.MOD PERFORM UDT.COMMAND CAPTURING UDT.RESPONSE * ** Now open the temporary file OPEN '', TEMP.NAME TO TEMP.HANDLE ELSE ERROR.MSG = "Error opening ":TEMP.NAME:" file" GOSUB SHOW.MESSAGE STOP END OPEN 'DICT', TEMP.NAME TO TEMP.DICT ELSE ERROR.MSG = "Error opening DICT ":TEMP.NAME:" file" GOSUB SHOW.MESSAGE STOP END * ** Display verbose information IF VERBOSE THEN PRINT "(Create Temp File)" PRINT TEMP.NAME:' file created with MOD = ' : TEMP.MOD PRINT END RETURN ! ** Put selection values into temp file *************** LOAD.TEMP.FILE: *************** * EMPTY.STRING = '' MORE.IDS = 1 [[LoadCnt]] = 0 LOOP REMOVE ID FROM SOURCE.ID.LIST SETTING MORE.IDS WRITEVU EMPTY.STRING ON TEMP.HANDLE, ID, 0 [[LoadCnt]] += 1 WHILE MORE.IDS DO REPEAT * ** Reset internal udt REMOVE pointer SOURCE.ID.LIST = SOURCE.ID.LIST * ** Display verbose information IF VERBOSE THEN PRINT "(Loaded List to Temp File) - " : [[LoadCnt]] : " items." PRINT END RETURN * ** Create the resulting list *************** BUILD.LIST2: *************** * TRANS.STMT = "TRANS('" : TEMP.NAME : "'," : DICT.NAME : ",'@ID','X')" IF DEST.LIST.NAMED THEN UDT.COMMAND = 'select ':FILE.NAME:' WITH EVAL "':TRANS.STMT:'" GT "" ' PERFORM UDT.COMMAND CAPTURING UDT.RESPONSE PERFORM 'SAVE.LIST ':DEST.LIST END ELSE UDT.COMMAND = 'select ':FILE.NAME:' WITH EVAL "':TRANS.STMT:'" GT "" TO ':DEST.LIST PERFORM UDT.COMMAND CAPTURING UDT.RESPONSE IF NOT(VERBOSE) THEN HUSH ON PERFORM 'SAVE.LIST ':TEMP.NAME IF NOT(VERBOSE) THEN HUSH OFF END * ** Display verbose information IF VERBOSE THEN PRINT "(Selected Result List)" PRINT "UDT.COMMAND = ":UDT.COMMAND PRINT "UDT.RESPONSE = ":UDT.RESPONSE PRINT "Destination ":DEST.LIST PRINT "Named List ":DEST.LIST.NAMED PRINT END RETURN ! ** Remove temporary key list file *************** FINISH.UP: *************** * ** Close and delete the temporary file CLOSE TEMP.HANDLE CLOSE TEMP.DICT UDT.COMMAND = 'DELETE.FILE ':TEMP.NAME DATA 'Y' PERFORM UDT.COMMAND CAPTURING UDT.RESPONSE * ** Display verbose information IF VERBOSE THEN PRINT "(Delete Temp File)" PRINT TEMP.NAME:' file deleted...' PRINT END * ** Create a currently active select list (if no to-list defined) IF NOT(DEST.LIST.NAMED) THEN PERFORM 'GET.LIST ':TEMP.NAME CAPTURING UDT.RESPONSE READSELECT SOURCE.ID.LIST ELSE SOURCE.ID.LIST = NULL$ PERFORM 'DELETE.LIST ':TEMP.NAME CAPTURING UDT.RESPONSE FORMLIST SOURCE.ID.LIST END RETURN ! ** Display error messages *************** SHOW.MESSAGE: *************** * PRINT ERROR.MSG PRINT "Press <cr> To Continue": INPUT DUMMY RETURN * **----------------------------------------------------------------------** ** ** ** E N D O F P R O G R A M ** ** ** **----------------------------------------------------------------------** * *************** END.OF.PROGRAM: *************** * END
A use of the program would look like:
2 Dev (0)-> SELECT MASTER WITH YREND NE "12"
4 records selected to list 0.
2 Dev (0)-> SAVE-LIST MY.LIST Overwriting existing saved list. 4 key(s) saved to 1 record(s). 2 Dev (0)-> LSELECT ARTMASTER WITH CLIENTNO IN MY.LIST VERBOSE (Parsed Command) LSELECT ARTMASTER WITH CLIENTNO IN MY.LIST TO 0
(Selected List) List Source MY.LIST found 4 items.
(Create Temp File) LSELECT0021 file created with MOD = 5
(Loaded List to Temp File) - 4 items.
235 key(s) saved to 1 record(s). (Selected Result List) UDT.COMMAND = select ARTMASTER WITH EVAL "TRANS('LSELECT0021',CLIENTNO,'@ID','X') " GT "" TO 0 UDT.RESPONSE = ■235 records selected to list 0.■■ Destination 0 Named List 0
(Delete Temp File) LSELECT0021 file deleted...
2 Dev (0)-> SSCROLL ARTMASTER
Command => SORT ARTMASTER 09:11:36 Oct 18 2012 ARTMASTER... CUSTOMER NAME (LFM)............ BT MOVE-IN. PRICHG$... BAL DUE... 120*1 ROBINSON, JAMES 05-17-07 210.00 0.00 120*2 ROBINSON, KATHRYN J 06-18-08 210.00 210.00 120*3 GARCIA, SAMANTHA L 08-13-09 210.00 -210.00 120*4 ROBINSON, CAROL A 03-15-95 210.00 210.00 120*5 ROBINSON, AARON L 09-19-06 210.00 210.00 . .
I hope this is of some help.