Oracle text search on multiple tables and joins
I usually solve fulltext searches on multiple columns on different tables by materializing a structured XML view of them and then creating the index on the whole XML.
This solution is generic and also give you freedom on search: the whole view or only a subpath. The drawback is managing the refresh of a MV who usually cannot be refreshed fast; but update of fulltext index usually isn't in real-time, too, so you can just schedulate it.
-- Crating the view
CREATE MATERIALIZED VIEW fulltext_helper
NOLOGGING
BUILD DEFERRED
REFRESH COMPLETE ON DEMAND
AS
SELECT
a.dob, -- we don't need to fulltext on him
XMLELEMENT(helper,
XMLFOREST(a.emp_no AS emp_no,
a.dept_no AS dept_no,
b.emp_name AS emp_name)
) AS indexme
FROM v_depts a
LEFT OUTER JOIN employee_details b
ON (a.emp_no = b.emp_no);
-- Creating the index
BEGIN
ctx_ddl.create_preference('fulltext_helper_lexer', 'BASIC_LEXER');
ctx_ddl.create_preference('fulltext_helper_filter', 'NULL_FILTER');
END;
/
CREATE INDEX fulltext_helper_index ON fulltext_helper (indexme)
INDEXTYPE IS CTXSYS.CONTEXT PARAMETERS (
'DATASTORE CTXSYS.DIRECT_DATASTORE
LEXER fulltext_helper_lexer
FILTER fulltext_helper_filter');
-- Searching the whole data
SELECT * FROM fulltext_helper
WHERE contains(indexme, '{abc} INPATH (/helper)') > 0;
-- Searching only on "empno"
SELECT * FROM fulltext_helper
WHERE contains(indexme, '{abc} INPATH (/helper/emp_no)') > 0;
Joining multiple tables ORACLE
This would be equivalent (if we also add the additional criteria you mentioned):
FROM
SD
INNER JOIN STORE as S
on S.STOREID = SD.STOREID
INNER JOIN MATERIAL as M
ON M.MATERIALID = SD.MATERIALID
LEFT JOIN STOREBIN as SB
ON SB.STOREBINID = SD.STOREBINID
LEFT JOIN VENDOR as V
ON V.VENDORID = SD.VENDORID
LEFT JOIN MATERIALPRICE as MP
ON MP.MATERIALID = M.MATERIALID
Oracle Text Search on certain columns
Giving the path "/HELPER/EMP_NAME/SUPERVISOR" tells him to search on leaf like "...", which doesn't exists; furthermore you shoud specify the INPATH operator.
The right syntax is:
CONTAINS(indexme,'jack INPATH(/HELPER/EMP_NAME) and jill INPATH(/HELPER/SUPERVISOR)') > 0;
Oracle SQL Query to join multiple tables
The query should look like this:
select e.ENCNTR_ID as e_id, p.PERSON_ID as p_id, e.REG_DT_TM as admitted, ce.EVENT_ID as event_id
from ENCOUNTER e join
person p
on e.person_id = p.person_id left join
CLINICAL_EVENT ce
on ce.ENCNTR_ID = e.ENCNTR_ID and
ce.EVENT_CD in (1235764, 22161234) and
ce.valid_until_dt_tm > sysdate left join
CE_BLOB cb
on ce.EVENT_ID = cb.EVENT_ID and
cb.valid_until_dt_tm > sysdate
where e.reg_dt_tm > date '2018-01-01' and
e.reg_dt_tm < date '2018-01-02' and
e.active_ind = 1 and
e.encntr_type_cd = 7113.00 and
e.ACTIVE_STATUS_CD = 22223
order by e.REG_DT_TM, ce.PERFORMED_DT_TM, ce.CLINICAL_EVENT_ID;
Notes:
- Never use commas in the
FROM
clause. Always use proper, explicit, standardJOIN
syntax. - The
WHERE
clause goes after theFROM
clause. JOIN
is an operator in theFROM
clause, so allJOIN
s need to be before theWHERE
.- Use the keyword
DATE
for date constants.
Join Multiple tables in oracle sql
This is the query using join:
select p.p_name,c.c_name,s.s_name,s.s_contact,b.b_name,b.b_contact
from product p
join buyer b on p.p_id = b.p_id and <second condition>
join category c on p.p_id = c.p_id
join seller s on c.p_id = s.p_id
where p.p_id="123" ;
Combining values from multiple tables using join clause with multiple ON
This approach uses UNION ALL
to combine the letter named tables (tbla, tblb, tblc, tbld) into a CTE
, common table expression. The combined table is then summarized by id, [desc] and crosstabulated (or pivoted) across the login columns. The pivoted result is then LEFT JOIN
'ed to the master_tbl. Something like this.
with
tbl_cte(tbl, id, [login], [desc]) as (
select 'A', * from tbla
union all
select 'B', * from tblb
union all
select 'C', * from tblc
union all
select 'D', * from tblc),
pvt_cte(id, tbla_login, tblb_login, tblc_login, tbld_login, [desc]) as (
select id,
max(case when tbl='A' then [login] else null end) as tbla_login,
max(case when tbl='B' then [login] else null end) as tblb_login,
max(case when tbl='C' then [login] else null end) as tblc_login,
max(case when tbl='D' then [login] else null end) as tbld_login,
[desc]
from tbl_cte
group by id, [desc])
select mt.id, [name], country, [status], pc.tbla_login,
pc.tblb_login, pc.tblc_login, pc.tbld_login, pc.[desc]
from master_tbl mt
left join pvt_cte pc on mt.id=pc.id;
Search across multiple tables and also display table name in resulting rows
You are looking for dynamic SQL. Assemble your query from the system catalog automatically:
SELECT string_agg('SELECT student_name, '''
|| c.oid::regclass || ''' AS tbl, pid FROM '
|| c.oid::regclass
|| $$ WHERE student_name = 'John Doe'$$
, E'\nUNION ALL\n')
FROM pg_namespace n
JOIN pg_class c ON c.relnamespace = n.oid
WHERE n.nspname = 'public' -- schema name where your tables lie
AND c.relname LIKE 't%' -- and / or filter table names
AND EXISTS (
SELECT 1 FROM pg_attribute
WHERE attrelid = c.oid
AND attname = 'student_name' -- make sure column exists
AND NOT attisdropped -- and is alive
);
Produces the query string:
SELECT student_name, 'tbl1' AS tbl, pid FROM tbl1 WHERE student_name = 'John Doe'
UNION ALL
SELECT student_name, 'tbl2' AS tbl, pid FROM tbl2 WHERE student_name = 'John Doe'
UNION ALL
SELECT student_name, 'tbl3' AS tbl, pid FROM tbl3 WHERE student_name = 'John Doe'
...
Then run it in a second call or completely automate it with a PL/pgSQL function using EXECUTE
. Example:
Select a dynamic set of columns from a table and get the sum for each
This query produces safe code with sanitized identifiers preventing SQL injection. (Explanation for oid::regclass
here.)
There are more related answers. Use a search.
BTW, LIKE
in student_name LIKE 'John Doe'
is pointless. Without wildcards, just use =
.
How to query specific column name from multiple table from SQL
Because user_tab_columns
has table_name
and column_name
in each rows, so your select only omit the row with that columns, not other rows with other columns of that table.
One query you could use is:
SELECT DISTINCT table_name
FROM user_tab_columns c
WHERE NOT EXISTS (
SELECT 1
FROM user_tab_columns
WHERE column_name LIKE '%OBJECT_NO%'
AND table_name = c.table_name
)
ORDER BY table_name;
Other way could work is:
SELECT DISTINCT table_name
FROM user_tab_columns
WHERE table_name NOT IN (
SELECT table_name
FROM user_tab_columns
WHERE column_name LIKE '%OBJECT_NO%'
)
ORDER BY table_name;
Related Topics
Can a Stored Procedure Work with Two Different Databases? How About Two Servers
Oracle Text Escaping with Curly Braces and Wildcards
Adding Extra Column to View, Which Is Not Present in Table
Sql Server Equivalent of Postgresql Distinct on ()
String Equivalent of Sum to Concatenate
Sql Create Database If Not Exists, Unexpected Behaviour
Display All Data of All Tables
Why Is There a Scan on My Clustered Index
How to Alter a Column Datatype for Derby Database
How to Set a Jdbc Timeout for a Single Query
Sql 2005 How to Use Keyword Like in a Case Statement
Oracle Locking with Select...For Update Of
Count Data as Zero If It Is Null When Where Clause Is Used
Sqlite: Autoincrement Primary Key Questions
Postgresql Multiple Nullable Columns in Unique Constraint