Assuming that each of your tables has a similar structure (i.e. every table has columns similar to rep, mgr, mgr2, mgr3, mgr4, etc). You could create a function that checks all of those columns dynamically if they exist and return either a true or false condition.
The following function takes in the value you want to search for - the PERSON_LOGGED_IN (assumed to be an integer key value for the purpose of the answer) and a table schema and name to look into (schema name is included to ensure duplicate tables names in different schemas don't conflict).
We then get a list of all columns in the specified table that match your set of criteria (rep, mgr, mgr2, etc). The benefit of this is that if you have different columns in different tables, you can specify all of them that could match and only those that actually exist in the table will be checked against.
After the matching columns are determined, then we just check the number of rows that match and return either a 1 or 0. I'm returning a numeric value because plain SQL doesn't recognize boolean values like PL/SQL does.
Your final query would become:
SELECT *
FROM BOATS
WHERE IN_HIERARCHY(PERSON_LOGGED_IN, 'SCHEMA.BOATS') = 1
And here's the function:
CREATE OR REPLACE FUNCTION IN_HIERARCHY (
PERSON_LOGGED_IN IN PLS_INTEGER,
TABLE_SCHEMA_AND_NAME IN VARCHAR2
) RETURN PLS_INTEGER
IS
MATCHING_COLUMNS VARCHAR2(200);
NUMBER_OF_ROWS_FOUND PLS_INTEGER := 0;
BEGIN
select LISTAGG(COLUMN_NAME, ',') WITHIN GROUP (ORDER BY COLUMN_NAME)
INTO MATCHING_COLUMNS
from all_tab_columns
where OWNER = regexp_substr(TABLE_SCHEMA_AND_NAME,'[^.]+', 1, 1)
AND TABLE_NAME = regexp_substr(TABLE_SCHEMA_AND_NAME,'[^.]+', 1, 2)
and COLUMN_NAME in ('REP', 'MGR', 'MGR2', 'MGR3', 'MGR4');
EXECUTE IMMEDIATE
'SELECT COUNT(*)
FROM ' || TABLE_SCHEMA_AND_NAME || '
WHERE :PERSON_LOGGED_IN IN (' || MATCHING_COLUMNS || ')'
INTO NUMBER_OF_ROWS_FOUND
USING PERSON_LOGGED_IN;
IF NUMBER_OF_ROWS_FOUND > 0 THEN
RETURN 1;
ELSE
RETURN 0;
END IF;
END;
/
Side note: I don't personally know of a way to get the list of tables in the from clause from within this function based on the statement that's executing it, but if you can somehow find a way to determine that, you could theoretically also eliminate the table name argument from the function as well. However, it's probably not worth it and the actual where clause would likely be less clear to the reader.
Then again, as @kordirko pointed out, if you're really just interested in simplifying the query and making it more readable, then something like this would be a lot simpler:
SELECT *
FROM BOATS
WHERE PERSON_LOGGED_IN IN (REP, MGR, MGR2, MGR3, MGR4)
Person_logged_inand five more for the employee levels), and so your query might becomeselect * from boats where in_hiearchy(person_logged_in, rep, mgr, mgr2, mgr3, mgr4) = 1ANYoperator:SELECT * FROM boat WHERE Person_logged_in = Any( Mgr, mgr2, mgr3, mg4 )