Joining 3 tables in Oracle - oracle

I need to join three tables in Oracle; I have code but I am not sure if it is totally right.
FROM DISTRICT D1
JOIN EMPLOYEE E1 ON D1.DISTRICT_ID = E1.DISTRICT_ID
JOIN TOTAL_PAB T1 ON E1.EMP_ID = T1.EMP_ID
I need to join the table DISTRICT, EMPLOYEE, AND TOTAL_PAB.
Where do the primary and foreign keys go in this join table statement?
Primary key for EMPLOYEE is EMP_ID and FK is DISTRICT_ID.
Primary key for DISTRICT is DISTRICT_ID and FK is SUPERINTENDENT_ID.
Primary key for TOTAL_PAB is PAB_ID and FK is EMP_ID.

The query seems legit, but you should give us some more informations for a better answer.
Generally, it's not important if a field is key or not: the important thing is that ONLY fields in "ON" part of the join statement will be used for matching rows.

Related

Deleting data from one table using data from a second table

I have a table table1, where there is a million data and a completely identical table table2, only there are only 106 data. How it is possible to delete these 106 data from table1?
In these two tables i have fields like id, date, param0, param1, param2.
Presuming that uniqueness is enforced through the ID column in both tables, then:
delete from table1 a
where exists (select null
from table2 b
where b.id = a.id
);
Otherwise, add some more columns (into the where clause) which will help you delete only rows you really want.

Oracle SQL: Single Index with two Columns vs index on one Column

I'm using Oracle12c
I have a table with a primary key and separate column.
create tableB(
ID number(10)
,data number(10)
);
ID is my primary key.
I have to join 3 tables on my query and the performance issue is the B.data without an index.
B.data contains 'null' values and multiple entries on the same numbers.
select A.examp from tabled D
join tableb B on D.data = B.data
join tablec C on B.ID = C.ID
join tablea A on C.val = A.val
where D.ID = :value;
So my question is what is the difference between an index that contains only one value like the data column
create index ind_tableb on tableb (data);
and an index that contains multiple columns like
create index ind_tableb on tableb (data, id);
Can i get an improvement by selecting the id in the index with the data in the way i join the columns ?
Thanks for any advise and help.
For this particular query, you want the two column index version:
create index ind_tableb on tableb (data, id);
The above index, if used, would let Oracle rapidly lookup tabled.data values for a potential match with a tableb.data value. If a match be found, then the same index would also contain the tableb.ID value for the next join to tablec. If you just used the single column version on tableb.data alone, then Oracle would have to seek back to the tableb table to find the ID values. This could hurt performance and might even cause the index to not be used.

Using "contains" as a way to join tables?

The Primary key in table one is used as in table 2 but it is modified as so:
Primary key Column in table 1: 123abc
Column in table 2: 123abc_1
I.e. the key is used but then _1 is added to create a unique value in the column of Table 2.
Is there any way that I can join the two tables, the data in the 2 columns is not identical but it very similar. Could I do something like:
SELECT *
FROM TABLE1 INNER JOIN
TABLE2
ON TABLE1.COUMN1 contains TABLE2.COLUMN2;
I.e. checking that the value in Table 1 is within the value in Table 2?
You can check only the first part of column2; for example
SELECT *
FROM TABLE1 INNER JOIN TABLE2
ON INSTR(COLUMN2, COLUMN1) = 1
or
ON COLUMN2 LIKE COLUMN1 || '%'
However, keeping foreign key in such a way can be really dangerous, not to think about performance on large DBs.
You'd better use a different column in Table2 to store the key of Table 1, even adding a constraint.

Missing right parenthesis- ORA-00907

select distinct student.ID
from (student join takes using(ID))
join (instructor join teaches using(ID))
using(course_id, sec_id, semester, year)
where instructor.name = 'Einstein'
As rightly pointed out Bob, there was a '_' in that. But now it says USING cannot have qualifier.
Student :
create table student
(ID varchar(5),
name varchar(20) not null,
dept_name varchar(20),
tot_cred numeric(3,0) check (tot_cred >= 0),
primary key (ID),
foreign key (dept_name) references department
on delete set null
)
Takes:
create table takes
(ID varchar(5),
course_id varchar(8),
sec_id varchar(8),
semester varchar(6),
year numeric(4,0),
grade varchar(2),
primary key (ID, course_id, sec_id, semester, year),
foreign key (course_id,sec_id, semester, year) references section
on delete cascade,
foreign key (ID) references student
on delete cascade
)
Instructor:
create table instructor
(ID varchar(5),
name varchar(20) not null,
dept_name varchar(20),
salary numeric(8,2) check (salary > 29000),
primary key (ID),
foreign key (dept_name) references department
on delete set null
)
Teaches :
create table teaches
(ID varchar(5),
course_id varchar(8),
sec_id varchar(8),
semester varchar(6),
year numeric(4,0),
primary key (ID, course_id, sec_id, semester, year),
foreign key (course_id,sec_id, semester, year) references section
on delete cascade,
foreign key (ID) references instructor
on delete cascade
);
I have pasted the structure as requested. I hope that helps!
I have also tried editing the quotes but still no use.
The problem is not that there are too few parentheses but that there are too many.
I'm guessing a bit here because I don't know exactly what your tables look like, but it appears that your SELECT statement should be:
select distinct student.ID
from student
join takes
using(ID)
join instructor
using(ID)
join teaches
using(course id, sec id, semester, year)
where instructor.name = 'Einstein'
In addition, you need to be careful about the editor you're using. In your question the single quotes surrounding 'Einstein' are not real single quotes - they appear to be Unicode apostrophes as would be added by a word processor such as Microsoft Word. String constants need to be surrounded by single quote characters (') - using anything else will cause errors.
Best of luck.
As Bob Jarvis pointed out, the third using clause has spaces where there should be underscores; changing those then gets (as you edited the question to say):
ORA-25154: column part of USING clause cannot have qualifier
because the select list has student.ID. When you use the using clause the column(s) in that can't be referenced directly in the joined tables, so you need to do:
select distinct ID
from (student join takes using(ID))
join (instructor join teaches using(ID))
using(course_id, sec_id, semester, year)
where instructor.name = 'Einstein';
... but that will now get
ORA-00918: column ambiguously defined
... because both student and instructor have ID columns, which is presumably why the select list was prefixed in the first place. You could use an inline view to lose the instructor ID from the select list scope:
select distinct ID
from (student join takes using(ID))
join (select course_id, sec_id, semester, year, name
from instructor join teaches using(ID)) instructor
using(course_id, sec_id, semester, year)
where instructor.name = 'Einstein';
But really you'd be better off avoiding using here and instead use the on syntax and simplified joins, e.g.:
select distinct stu.id
from instructor ins
join teaches tea on tea.id = ins.id
join takes tak on tak.course_id = tea.course_id
and tak.sec_id = tea.sec_id
and tak.semester = tea.semester
and tak.year = tea.year
join student stu on stu.id = tak.id
where ins.name = 'Einstein';
Also see an earlier related answer for more.

What is the correct order in which tables should be joined

I have three tables
TABLE 1
PLANS -> Has all the plans information
COLUMNS:
PLAN_ID
PLAN_NAME
OTHER_DETAILS
(PLAN_ID is the PRIMARY KEY)
TABLE 2
REGISTER ->
COLUMNS:
RUN_ID
PLAN_ID
REGISTER_DETAILS
(RUN_ID AND PLAN_ID) is the primary key
TABLE 3
ELECTION ->
Columns
RUN_ID
PLAN_ID
ELECTION_DETAILS
(RUN_ID AND PLAN_ID) is the primary key
PLAN_ID could be present in either REGISTER (or) ELECTION (or) BOTH tables.
For an input RUN_ID , I need to pick rows in the below format such that if a plan has only register details only REGISTER_DETAILS is picked.
If a plan has both REGISTER_DETAILS and ELECTION_DETAILS then both the details should get returned.
Report Format:
RUN_ID PLAN_ID REGISTER_DETAILS ELECTION_DETAILS
Solution
I tried by joining the tables in below format:
SELECT
..
FROM
PLANS A
LEFT JOIN REGISTER B
ON (A.PLAN_ID = B.PLAN_ID
AND B.RUN_ID = 'Input Run Id')
LEFT JOIN ELECTION C
ON (A.PLAN_ID = C.PLAN_ID
AND C.RUN_ID = 'Input Run Id')
But this is also returning plans that are not present in REGISTER and ELECTION tables.
Can someone please tell what is wrong with the query?
Add
WHERE B.PLAN_ID IS NOT NULL OR
C.PLAN_ID IS NOT NULL
to the end of your query.
Best of luck.

Resources