2

Anyone please help me for ABL equivalent for SELECT IN statement For e.g.

SELECT column_name(s)
FROM table_name
WHERE column_name IN (value1,value2,...);
Izzy
  • 6,740
  • 7
  • 40
  • 84
user2112700
  • 121
  • 2
  • 8

5 Answers5

2

OR is obviously simplest but since that has been declared as unacceptable perhaps this would meet the need?

define variable i as integer no-undo.
define variable n as integer no-undo.
define variable cityList as character no-undo.

cityList = "boston,new york,chicago,...".

n = num-entries( cityList ).
do for i = 1 to n:
  for each customer no-lock where city = entry( i, cityList ):
    display customer.name customer.city.
  end.
end.

This will avoid table scans and be about as efficient as the OR since the field comparison is an equality match.

Tom Bascom
  • 13,405
  • 2
  • 27
  • 33
2

CAN-DO Function

* Returns TRUE if a character value exists in a comma-delimited list; otherwise returns FALSE
* Use the CAN-DO function instead of stringing many OR conditions together
* Example

      IF CAN-DO(“A,B,C,D",x) THEN MESSAGE “Value is in set”.
Kenji K.
  • 21
  • 1
1

There is no in-built IN operator in Progress 4GL/ABL. You can use OR operator for this purpose. An example:

FOR EACH customer WHERE city = 'boston' OR city = 'salo' OR city = 'paris':
        DISP customer.NAME.
END.
Austin
  • 1,237
  • 1
  • 11
  • 22
  • OR Operator would not satisfy my needs here :( Is there some other alternate for IN operator ?? – user2112700 Oct 28 '14 at 13:13
  • 1
    In what way does OR not meet your needs? – Tom Bascom Oct 28 '14 at 13:18
  • I want to update, quite a large records, So I have used OR where some records or not updated. – user2112700 Oct 29 '14 at 04:39
  • Could you elaborate? I'm not understanding what that means or why it would eliminate OR. – Tom Bascom Oct 29 '14 at 10:47
  • I have to update 3 columns, with more than 500 values, so it would be a large query. – user2112700 Oct 30 '14 at 06:43
  • Where did the list of 500 come from? If you built that in a previous query then you probably ought to be doing a join or using a loop like the one that I showed. Using LOOKUP() in a WHERE clause will turn the query into a table scan. That's not going to be good for performance. – Tom Bascom Oct 30 '14 at 21:04
1

As Austin says: you can use OR.

I will try to elaborate this a bit: using a dynamic query you could create a more flexible approach than a simple "FOR EACH" - like if you have a varying number of OR statements each time you run the query.

A quick and dirty example:

/* Definitions */
DEFINE VARIABLE cQuery       AS CHARACTER   NO-UNDO.
DEFINE VARIABLE cInString    AS CHARACTER   NO-UNDO.
DEFINE VARIABLE cOrStatement AS CHARACTER   NO-UNDO.
DEFINE VARIABLE iEntry       AS INTEGER     NO-UNDO.

/* Defining a temp-table to query */
DEFINE TEMP-TABLE client
    FIELD clientId AS INTEGER
    FIELD city     AS CHARACTER.

/* And a query */
DEFINE QUERY qClient FOR client.

/* Create some bogus data */
CREATE client.
ASSIGN 
    client.clientId = 1
    client.city     = "Rome".

CREATE client.
ASSIGN 
    client.clientId = 2
    client.city     = "Barcelona".

CREATE client.
ASSIGN 
    client.clientId = 3
    client.city     = "Paris".

CREATE client.
ASSIGN 
    client.clientId = 4
    client.city     = "Prague".

/* These are the cities we are searching for */
cInString = "Rome,Stockholm,Prague".

/* Convert the comma-separated list of cities to an "OR-statement" */
DO iEntry = 1 TO NUM-ENTRIES(cInString):
    cOrStatement = cOrStatement + (IF cOrStatement = "" THEN "" ELSE " OR ") + "client.city = " + QUOTER(ENTRY(iEntry,cInString)).
END.

/* Add () around the or-statement just to be sure */
cOrStatement = "(" + cOrStatement + ")".

/* Put together the query */
cQuery = "FOR EACH client WHERE " + cOrStatement.

/* Attach the query-string to the query */
QUERY qClient:QUERY-PREPARE(cQuery).

/* Open the query ...*/
QUERY qClient:QUERY-OPEN().

/* And get the first result */
GET FIRST qClient.

/* Iterate through results as long as there are any... */
DO WHILE AVAILABLE client:
    DISP client WITH FRAME x1 10 DOWN.

    DOWN WITH FRAME x1.
    GET NEXT qClient.
END.

/* Close query */
QUERY qClient:QUERY-CLOSE().
Jensd
  • 7,886
  • 2
  • 28
  • 37
0

You can use LOOKUP function like this:

DEFINE VARIABLE wc-liste AS CHARACTER  NO-UNDO.
DEFINE VARIABLE wc-sep   AS CHARACTER  NO-UNDO.

wc-sep = ",".

wc-liste = value1 + wc-sep + value2 + wc-sep + value3...

FOR EACH table_name
    WHERE LOOKUP(table_name.column_name, wc-liste, wc-sep) > 0
    NO-LOCK:
    ...
END.

But it's not a good idea for perfomances.

you can also try this:

bcle:
FOR EACH table_name
    NO-LOCK:
    IF LOOKUP(table_name.column_name, wc-liste, wc-sep) = 0 
    THEN 
        NEXT bcle.
    ...
END.
doydoy44
  • 5,720
  • 4
  • 29
  • 45
  • Both will actually have same performance since youre reading the entire table. – Jensd Oct 28 '14 at 17:53
  • @Jensd:even with an index on another field? I thought that using the function in the query break the index. In any case, thank you for this return. :) – doydoy44 Oct 28 '14 at 18:20
  • Thanks, and the second one will work very efficient, since I tried this earlier. Instead of lookup in table column, is it possible to lookup a column in a excel sheet ?? (I have tried input stream but couldn't lookup a specific column ) – user2112700 Oct 29 '14 at 05:02
  • @user2112700: I guess yes, Lookup function work with a constant, field name, variable name or expression (see the Progress doc). :) – doydoy44 Oct 29 '14 at 08:14
  • @user2112700: If this answer or another (I like the answers of Jensd and Tom Bascom), please, validate it. – doydoy44 Oct 29 '14 at 08:26
  • 1) A more complex query might (or might not) effect what indices are used. You can do FOR EACH TABLE-SCAN: on any "table-scan" query (on newer releases of Openedge). 2) Querying an Excel-sheet is another thing altogether.
    – Jensd Oct 29 '14 at 09:05
  • Thanks everyone for helping :) Enjoy coding :) – user2112700 Oct 30 '14 at 11:56
  • @user2112700: You're welcome, happy for you. ;) Thank's for the return. Good Luck. – doydoy44 Oct 30 '14 at 13:13
  • Thank you for those who voted down. This answer was not the best (especially at performance level, what I wrote), but remained good and she was in the mind of `WHERE column_name IN (value1, value2, ...)`. Furthermore is that which has been validated (so that answered the question) ... – doydoy44 Oct 31 '14 at 10:36