INNER Join ORACLE [closed] - oracle

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I am having a issue with my INNER join for Oracle. I was hoping you guys could review. Basically the Address table houses addresses of incident and person. I basically need to do a SELECT statement for the incident address then an INNER join to get the persons address as well, for some reason it is not working.
select DISTINCT INCIDENT_PEOPLE_VW.INC_REPORT_NUMBER,trunc((to_number(to_char (offense_status_date,'yyyymmdd'))-to_number(to_char(DOB,'yyyymmdd')))/10000) as AGE,
INCIDENT_PEOPLE_VW.INCIDENT_ID,
OFFENSES.OFFENSE_STATUS_DATE,
INCIDENT_PEOPLE_VW.AGNCY_CD_AGENCY_CODE,
INCIDENT_PEOPLE_VW.STATUS,
INCIDENT_PEOPLE_VW.SEX_SEX_CODE,
INCIDENT_PEOPLE_VW.RACE_RACE_CODE,
INCIDENT_PEOPLE_VW.LNAME,
INCIDENT_PEOPLE_VW.FNAME,
INCIDENT_PEOPLE_VW.DOB,
OFFENSES.REMARKS,
OFFENSE_CODES.OFFENSE_DESC,
P.LONGITUDE,P.LATITUDE,
suspicion_Codes.DESCRIPTION,
P.STREET_NUMBER, P.STREET_NAME,P.STREET_CD_STREET_TYPE_CODE,P.CITY,P.STATE_CD_STATE_CODE,P.ZIP5,
AH.STREET_NUMBER, AH.STREET_NAME,AH.STREET_CD_STREET_TYPE_CODE,AH.CITY,AH.STATE_CD_STATE_CODE,AH.ZIP5
from
INCIDENT_PEOPLE_VW,
OFFICER_INCIDENTS,OFFENSES,OFFENSE_CODES, OFFICERS,
ADDRESSES P, INCIDENT_ADDRESSES,offender_suspicions,suspicion_Codes,person_addresses D
INNER JOIN ADDRESSES ah
ON D.address_id= ah.address_ID
where OFFICER_INCIDENTS.INC_INCIDENT_ID=INCIDENT_PEOPLE_VW.INCIDENT_ID
AND INCIDENT_PEOPLE_VW.INCIDENT_ID=INCIDENT_ADDRESSES.INCIDENT_ID
AND INCIDENT_ADDRESSES.ADDRESS_ID=P.ADDRESS_ID
AND INCIDENT_PEOPLE_VW.INCIDENT_ID = OFFENSES.INC_INCIDENT_ID
AND INCIDENT_PEOPLE_VW.INCIDENT_ID = OFFENDER_SUSPICIONS.OFFNSE_INC_INCIDENT_ID
AND OFFENDER_SUSPICIONS.SUSPICN_CD_SUSPICION_CODE =SUSPICION_CODES.SUSPICION_CODE
AND OFFENSES.OFFNS_CD_OFFENSE_CODE = OFFENSE_CODES.OFFENSE_CODE
AND OFFICER_INCIDENTS.OFF1_OFFICER_ID = OFFICERS.OFFICER_ID
and OFFICER_INCIDENTS.ORC_ROLE_CODE='R'
and incident_people_vw.status='A'
and INCIDENT_PEOPLE_VW.ROLE_ROLE_TYPE IN ('A','S')
AND trunc((to_number(to_char(offense_status_date,'yyyymmdd'))-to_number(to_char (DOB,'yyyymmdd')))/10000) <= 17

The exact reason for your query to fail is the one #Politank-Z wrote you ...
You are mixing ANSI syntax of joins with the "old" syntax with join predicates in the WHERE clause.
If you used the ANSI syntax consistently, you would easily spot the problem, being that your person_addresses table join lacks the actual join predicate and, as such, your DB server is doing a cartesian product instead, effectively devouring all of your temporary tablespace.
Here you are, a slight iterative revamp of your query ...
Iteration 1 - introducing basic indentation and remaking all WHERE-clause join predicates to ANSI joins
select distinct
INCIDENT_PEOPLE_VW.INC_REPORT_NUMBER,
trunc((to_number(to_char(offense_status_date,'yyyymmdd')) - to_number(to_char(DOB,'yyyymmdd')))/10000) as AGE,
INCIDENT_PEOPLE_VW.INCIDENT_ID,
OFFENSES.OFFENSE_STATUS_DATE,
INCIDENT_PEOPLE_VW.AGNCY_CD_AGENCY_CODE,
INCIDENT_PEOPLE_VW.STATUS,
INCIDENT_PEOPLE_VW.SEX_SEX_CODE,
INCIDENT_PEOPLE_VW.RACE_RACE_CODE,
INCIDENT_PEOPLE_VW.LNAME,
INCIDENT_PEOPLE_VW.FNAME,
INCIDENT_PEOPLE_VW.DOB,
OFFENSES.REMARKS,
OFFENSE_CODES.OFFENSE_DESC,
P.LONGITUDE,P.LATITUDE,
suspicion_Codes.DESCRIPTION,
P.STREET_NUMBER, P.STREET_NAME,P.STREET_CD_STREET_TYPE_CODE,P.CITY,P.STATE_CD_STATE_CODE,P.ZIP5,
AH.STREET_NUMBER, AH.STREET_NAME,AH.STREET_CD_STREET_TYPE_CODE,AH.CITY,AH.STATE_CD_STATE_CODE,AH.ZIP5
from
INCIDENT_PEOPLE_VW
join OFFICER_INCIDENTS
on OFFICER_INCIDENTS.INC_INCIDENT_ID = INCIDENT_PEOPLE_VW.INCIDENT_ID
join OFFENSES
on OFFENSES.INC_INCIDENT_ID = INCIDENT_PEOPLE_VW.INCIDENT_ID
join OFFENSE_CODES
on OFFENSE_CODES.OFFENSE_CODE = OFFENSES.OFFNS_CD_OFFENSE_CODE
join OFFICERS
on OFFICERS.OFFICER_ID = OFFICER_INCIDENTS.OFF1_OFFICER_ID
join INCIDENT_ADDRESSES
on INCIDENT_ADDRESSES.INCIDENT_ID = INCIDENT_PEOPLE_VW.INCIDENT_ID
join ADDRESSES P
on P.ADDRESS_ID = INCIDENT_ADDRESSES.ADDRESS_ID
join offender_suspicions
on OFFENDER_SUSPICIONS.OFFNSE_INC_INCIDENT_ID = INCIDENT_PEOPLE_VW.INCIDENT_ID
join suspicion_Codes
on SUSPICION_CODES.SUSPICION_CODE = OFFENDER_SUSPICIONS.SUSPICN_CD_SUSPICION_CODE
person_addresses D,
INNER JOIN ADDRESSES ah
ON ah.address_ID = D.address_id
where
OFFICER_INCIDENTS.ORC_ROLE_CODE = 'R' and
incident_people_vw.status = 'A' and
INCIDENT_PEOPLE_VW.ROLE_ROLE_TYPE IN ('A','S') and
trunc((to_number(to_char(offense_status_date,'yyyymmdd'))-to_number(to_char(DOB,'yyyymmdd')))/10000) <= 17
;
Iteration 2 - identifying mistakenly forgotten cartesian products (i.e. joins without a join predicate, because when you put all your join predicates to your WHERE clause, you EASILY forget some)
In this case it's the PERSON_ADDRESSES table.
Iteration 3 - fixing the missing join predicates
select distinct
INCIDENT_PEOPLE_VW.INC_REPORT_NUMBER,
trunc((to_number(to_char(offense_status_date,'yyyymmdd')) - to_number(to_char(DOB,'yyyymmdd')))/10000) as AGE,
INCIDENT_PEOPLE_VW.INCIDENT_ID,
OFFENSES.OFFENSE_STATUS_DATE,
INCIDENT_PEOPLE_VW.AGNCY_CD_AGENCY_CODE,
INCIDENT_PEOPLE_VW.STATUS,
INCIDENT_PEOPLE_VW.SEX_SEX_CODE,
INCIDENT_PEOPLE_VW.RACE_RACE_CODE,
INCIDENT_PEOPLE_VW.LNAME,
INCIDENT_PEOPLE_VW.FNAME,
INCIDENT_PEOPLE_VW.DOB,
OFFENSES.REMARKS,
OFFENSE_CODES.OFFENSE_DESC,
P.LONGITUDE,P.LATITUDE,
suspicion_Codes.DESCRIPTION,
P.STREET_NUMBER, P.STREET_NAME,P.STREET_CD_STREET_TYPE_CODE,P.CITY,P.STATE_CD_STATE_CODE,P.ZIP5,
AH.STREET_NUMBER, AH.STREET_NAME,AH.STREET_CD_STREET_TYPE_CODE,AH.CITY,AH.STATE_CD_STATE_CODE,AH.ZIP5
from
INCIDENT_PEOPLE_VW
join OFFICER_INCIDENTS
on OFFICER_INCIDENTS.INC_INCIDENT_ID = INCIDENT_PEOPLE_VW.INCIDENT_ID
join OFFENSES
on OFFENSES.INC_INCIDENT_ID = INCIDENT_PEOPLE_VW.INCIDENT_ID
join OFFENSE_CODES
on OFFENSE_CODES.OFFENSE_CODE = OFFENSES.OFFNS_CD_OFFENSE_CODE
join OFFICERS
on OFFICERS.OFFICER_ID = OFFICER_INCIDENTS.OFF1_OFFICER_ID
join INCIDENT_ADDRESSES
on INCIDENT_ADDRESSES.INCIDENT_ID = INCIDENT_PEOPLE_VW.INCIDENT_ID
join ADDRESSES P
on P.ADDRESS_ID = INCIDENT_ADDRESSES.ADDRESS_ID
join offender_suspicions
on OFFENDER_SUSPICIONS.OFFNSE_INC_INCIDENT_ID = INCIDENT_PEOPLE_VW.INCIDENT_ID
join suspicion_Codes
on SUSPICION_CODES.SUSPICION_CODE = OFFENDER_SUSPICIONS.SUSPICN_CD_SUSPICION_CODE
join person_addresses D
on D.<some column> = <some table from the above ones>.<some column from the table>
JOIN ADDRESSES ah
ON AH.address_id = D.address_id
where
OFFICER_INCIDENTS.ORC_ROLE_CODE = 'R' and
incident_people_vw.status = 'A' and
INCIDENT_PEOPLE_VW.ROLE_ROLE_TYPE IN ('A','S') and
trunc((to_number(to_char(offense_status_date,'yyyymmdd'))-to_number(to_char(DOB,'yyyymmdd')))/10000) <= 17
;
Iteration 4 - fixing the wonderfully strange age calculation, introducing consistent formatting and consistent table aliases to improve readability
select distinct
IP.incident_id, IP.inc_report_number,
-- trunc((to_number(to_char(OFS.offense_status_date,'yyyymmdd')) - to_number(to_char(IP.dob,'yyyymmdd')))/10000) as age,
months_between(OFS.offense_status_date, IP.dob) / 12 as age
OFS.offense_status_date,
IP.agncy_cd_agency_code, IP.status, IP.sex_sex_code, IP.race_race_code, IP.lname, IP.fname, IP.dob,
OFS.remarks,
OC.offense_desc,
AIA.longitude, AIA.latitude,
SC.description,
AIA.street_number, AIA.street_name, AIA.street_cd_street_type_code, AIA.city, AIA.state_cd_state_code, AIA.zip5,
PAA.street_number, PAA.street_name, PAA.street_cd_street_type_code, PAA.city, PAA.state_cd_state_code, PAA.zip5
from
incident_people_vw IP
join officer_incidents OI
on OI.inc_incident_id = IP.incident_id
join offenses OFS
on OFS.inc_incident_id = IP.incident_id
join offense_codes OC
on OC.offense_code = OFS.offns_cd_offense_code
join officers O
on O.officer_id = OI.off1_officer_id
join incident_addresses IA
on IA.incident_id = IP.incident_id
join addresses AIA
on AIA.address_id = IA.address_id
join offender_suspicions OS
on OS.offnse_inc_incident_id = IP.incident_id
join suspicion_codes SC
on SC.suspicion_code = OS.suspicn_cd_suspicion_code
join person_addresses PA
on PA.<some column> = <some table alias from the above ones>.<some column from the table>
join addresses PAA
on PAA.address_id = PA.address_id
where
OI.orc_role_code = 'R' and
IP.status = 'A' and
IP.role_role_type in ('A','S') and
-- trunc((to_number(to_char(OFS.offense_status_date,'yyyymmdd')) - to_number(to_char(IP.dob,'yyyymmdd')))/10000) <= 17
months_between(OFS.offense_status_date, IP.dob) / 12 <= 17
;
Enjoy. And from now on always use the ANSI join syntax.

Related

Many Joins with single conditions VS Fewer Joins with multiple conditions

I found a query on the back end of a report that has multiple joins to multiple tables and thought that I'd improve the performance of the query by reducing the number of joins and consolidating the conditions on those joins. My theory being that every join would force the query to go over that table againso, fewer joins equal fewer reads.
What I found:
SELECT /* person fields, address fields, contact fields */
FROM PositionHistory ph
LEFT JOIN Person p ON p.ID = p.ID AND ph.Active = 'Y'
LEFT JOIN PersonAddress pa1 ON pa1.AddrID = p.ID AND pa1.Type = 'Current'
LEFT JOIN Address a1 ON a1.ID = pa1.AddrID
LEFT JOIN PersonPhone pp1_p ON pp1_p.ID = pa1.PhoneID AND pp1_p.Type = 'Phone'
LEFT JOIN Phone p1_p ON p1_p = pp1_p.ID
LEFT JOIN PersonPhone pp1_c ON pp1_c.ID = pa1.PhoneID AND pp1_c.Type = 'Cell'
LEFT JOIN Phone p1_c ON p1_c = pp1_c.ID
LEFT JOIN PersonAddress pa2 ON pa2.AddrID = p.ID AND pa2.Type = 'Work'
LEFT JOIN Address a2 ON a2.ID = pa2.AddrID
LEFT JOIN PersonPhone pp2_p ON pp2_p.ID = pa2.PhoneID AND pp2_p.Type = 'Phone'
LEFT JOIN Phone p2_p ON p2_p = pp2_p.ID
LEFT JOIN PersonPhone pp2_c ON pp2_c.ID = pa2.PhoneID AND pp2_c.Type = 'Cell'
LEFT JOIN Phone p2_c ON p2_c = pp2_c.ID
LEFT JOIN OtherContact oc1 ON oc1.PersonID = p.ID AND oc1.Type = 'Work'
LEFT JOIN OtherContact oc2 ON oc2.PersonID = p.ID AND oc2.Type = 'Home'
All this in an effort to get the data onto one row for presentation in an SSRS report.
I found that by using a matrix in the report I could get the data onto one row so that wasn't an issue anymore but the report was slow to run and I thought I'd work on the query to improve performance. What I tried:
SELECT /* person fields, address fields, contact fields */
FROM PositionHistory ph
LEFT JOIN Person p ON p.ID = p.ID AND ph.Active = 'Y'
LEFT JOIN PersonAddress pa ON pa.AddrID = p.ID AND pa.Type IN ('Current','Work')
LEFT JOIN Address a ON a.ID = pa.AddrID
LEFT JOIN PersonPhone pp ON pp.ID = pa.PhoneID AND pp.Type IN ('Phone', 'Cell')
LEFT JOIN Phone p ON p = pp.ID
LEFT JOIN OtherContact oc ON oc.PersonID = p.ID AND oc.Type IN ('Work', 'Home')
The number of rows returned increased by about 5 times, which makes sense. But when I used SET STATISTICS IO ON; I found that the number of overall logical reads increased from 22.7k to 37.3k which is the opposite of what I expected. At the very least I'd think it would be the same. Wouldn't the query be traversing the data fewer times with fewer joins? I need to understand what's going on here so that I can develop well-performing queries going forward but the original query isn't something I would've ever thought to do!
I might as well use the original query for the report at this point since it (apparently, somehow, bafflingly) performs better and then the report itself doesn't have to process the data onto one row. Any thoughts on how to improve would be welcome! I'm sure I'm missing something basic but I haven't found anything online or as I've tweaked the query.

speed up a query with multiple inner joins in ms access

as tittle says i need to improve this query that i have made in ms access, the tables are from a linked DB. i can't index them. i need help to understand where it is taking so long... is there any function like
EXPLAIN to access? do i need to put more columns in some sort of group by? what i need to do to improve the speed of this (the group by of first select has 4M rows but after grouped only has 321k and it takes 20min to run when laptop doesn't crashes)
SELECT a.SEQ_NO,
b.SKU,
b.maxdate,
(a.BASE_COST/a.EXCHANGE) AS BASE_COST,
(a.NET_COST/a.EXCHANGE) AS NET_COST,
(a.NET_NET_COST/a.EXCHANGE) AS EXCHAGED_NET_NET_COST,
a.NET_NET_COST,
(a.DEAD_NET_NET_COST/a.EXCHANGE) AS DEAD_NET_NET_COST,
(a.LANDED_COST/a.EXCHANGE) AS LANDED_COST,
(a.POSEIMA/a.EXCHANGE) AS POSEIMA,
(a.TOTAL_BONUS/a.EXCHANGE) AS TOTAL_BONUS,
(a.IEC/a.EXCHANGE) AS IEC,
(a.IEC_BONUS/a.EXCHANGE) AS IEC_BONUS,
(a.ECO_INVOICE_FORN/a.EXCHANGE) AS ECO_INVOICE_FORN_SYSTEM,
(a.ECO_INVOICE/a.EXCHANGE) AS ECO_INVOICE_SYSTEM,
(a.ECO_MERCHANDISE/a.EXCHANGE) AS ECO_MERCHANDISE_SYSTEM,
c.SUPPLIER,
c.SUP_NAME,
d.UPC,
d.PRIMARY_UPC_IND,
f.BRAND,
g.DEPT,
g.DESC_UP,
g.CLASS,
g.SUBCLASS,
h.AV_COST,
h.UNIT_RETAIL AS Last_of_unit_retail,
h.STATUS, i.[UNIT VALUE],
i.[INITIAL DATE],
i.[END DATE] INTO PRICELIST
FROM (((((((RMS_MC_NB_PRICELIST_COST AS a INNER JOIN (SELECT MAX(SEQ_NO) AS
ID, SKU, MAX(ACTIVE_DATE) AS maxdate FROM RMS_MC_NB_PRICELIST_COST GROUP BY
SKU) AS b ON a.SEQ_NO = b.ID)
INNER JOIN RMS_MC_SUPS AS c ON a.SUPPLIER = c.SUPPLIER)
INNER JOIN RMS_MC_UPC_EAN AS d ON b.SKU = d.SKU)
INNER JOIN RMS_MC_WIN_ATTRIBUTES AS e ON b.SKU = e.SKU)
INNER JOIN RMS_MC_NB_BRAND AS f ON e.NB_BRAND_NO = f.BRAND_NO)
INNER JOIN RMS_MC_DESC_LOOK AS g ON b.SKU = g.SKU)
INNER JOIN RMS_MC_WIN_STORE AS h ON b.SKU = h.SKU)
LEFT JOIN MAPA_APOIOS_SISO AS i ON b.SKU = i.[# ARTICLE];

sql select records that don't have relation in a third table

I have three tables
CLAIMS_TB
CLAIMS_RISK_TB
VEHICLE_TB
And then I need this result below:
Who can help me or share with me the query to be used?
N.B: If the code is 700 it means that it is a vehicle and it must fill the column called "ai_vehicle_use" otherwise it must leave it blank because "VEHICLE_TB" table contains only vehicles
This is what I tried:
select
klm.CM_PL_INDEX,
klm.cm_no,
klmrisk.cr_risk_code,
CASE WHEN klm.CM_PR_CODE = '0700' THEN klmrisk.cr_risk_code ELSE '' END,
veh.ai_vehicle_use
from CLAIMS_TB klm
JOIN CLAIMS_RISK_TB klmrisk
ON (klm.cm_index = klmrisk.cr_cm_index)
INNER JOIN VEHICLE_TB veh
on veh.ai_regn_no = klm.cm_no
where klm.cm_no='CL/01/044/00001/01/2018'
or klmrisk.cr_cm_index='86594'
order by klmrisk.cr_risk_code;
I believe this could fit your needs.
SELECT
*
FROM CLAIMS_TB AS c
LEFT JOIN CLAIMS_RISK_TB cl ON c.cm_index = cl.cr_cm_index
LEFT JOIN VEHICLE_TB v ON cl.cr_risk_code = v.ai_risk_index
Finaly I find the solution, query below works:
select * from CLAIMS_TB c
JOIN CLAIMS_RISK_TB cr ON( C.CM_INDEX = cr.cr_cm_index)
LEFT OUTER JOIN VEHICLE_TB v ON (cr.cr_risk_code = v.ai_regn_no);

Multiple Joins LINQ Query performance

I'm new to LINQ and have very little knowledge.
I have the following complex query. it runs 3 or 4 times slower than the stored procedure which i translated to LINQ.
any tips for me to make it run faster?
var result = from a in db.A
join al in db.AL.Where(q => q.CurrentLocation == 1) on a.AID equals al.AID into tmp_al
from al in tmp_al.DefaultIfEmpty()
join l in db.Lon al.LID equals l.LID into tmp_l
from l in tmp_l.DefaultIfEmpty()
join r in db.R on l.RID equals r.RID into tmp_r
from r in tmp_r.DefaultIfEmpty()
join b in db.B on r.BID equals b.BID into tmp_b
from b in tmp_b.DefaultIfEmpty()
join ap in db.AP.Where(q => q.CurrentProtocol == 1) on a.AID equals ap.AID into tmp_ap
from ap in tmp_ap.DefaultIfEmpty()
join p in db.P on ap.PID equals p.PID into tmp_p
from p in tmp_p.DefaultIfEmpty()
join s in db.S on a.SID equals s.SID into tmp_s
from s in tmp_s.DefaultIfEmpty()
join ans in db.AS on a.ASID equals ans.ASID into tmp_ans
from ans in tmp_ans.DefaultIfEmpty()
join pr in db.P on p.PI equals pr.PID into tmp_pr
from pr in tmp_pr.DefaultIfEmpty()
where a.Active == 1
group a by new { a.Active, pr.LN, pr.FN, b.BN, r.RID, r.R1, p.PN, s.S1, ans.AS1 }
into grp
orderby grp.Key.BN, grp.Key.R1, grp.Key.PN, grp.Key.S1, grp.Key.AS1
select new
{
PIName = grp.Key.LN + " " + grp.Key.FN,
BN = grp.Key.BN,
RID = grp.Key.RID,
R = grp.Key.R1,
PN = grp.Key.PN,
S = grp.Key.S1,
AS = grp.Key.AS1,
NumberOA = grp.Count()
};
Thanks for your answers. #Albin Sunnanbo: i dont know how to check the execution plans. my LINQ runs correctly and produces the required output. it is just slow. I would like to speeden it up. #usr: the original sql is as follows:
sorry about the silly table names. the original code is confidential. so i'm not posting the complete table names.
CREATE PROCEDURE [dbo].[report_CBRP] --
AS
SELECT LN + ' ' + FN As PIN, BN, R.RID, R, PN,
S, AS, COUNT(*) As NOA
FROM A
LEFT JOIN AL
ON A.AID = AL.AID
AND AL.CL = 1
LEFT JOIN L
ON AL.LID = L.LID
LEFT JOIN R
ON L.RID = R.RID
LEFT JOIN B
ON R.BID = B.BID
LEFT JOIN AP
ON A.AID = AP.AID
AND AP.CPl = 1
LEFT JOIN P
ON AP.PID = P.PID
LEFT JOIN S
ON A.SID = S.SID
LEFT JOIN AS
ON A.ASID = AS.ASID
LEFT JOIN P
ON P.PI = P.PID
GROUP BY A.A, LN , FN , B.BN, R.RID, R.R, P.PN,
S.S, AS.AS
HAVING A.A = 1
ORDER BY B.BN, R.R, P.PN, S, AS
GO
It seems you're doing SQL hard life here.
In general, try to avoid so many joins, but rather break them into few small queries.
More than that, you're performing a group by which in itself is an expensive operation, let alone with so many columns
I've noticed that you're joining all the columns in each table. Try to select only the relevant columns.
Also noticed that few of the tables aren't used in the group by like al, ap and l. Do you need them at all??
Use AsNoTracking() for readonly data from EF. In that way you speed up things.
Use SQL Views

Oracle SQL developer how to display NULL value of the foreign key

I am going to try to use left outer join between Ticket and Membership.
However, it does not display the foreign key of NULL values on Ticket. Could you give me some answer for this what's wrong with this query?
Thanks.
FROM Ticket t, Production pro, Performance per, Price, Price_level, Booking, Customer, Customer_Concession ccons, Membership, Member_concession mcons
WHERE t.performanceid = per.performanceid AND
t.PRODUCTIONID = Price.PRODUCTIONID AND
t.levelId = Price.levelId AND
Price.PRODUCTIONID = pro.PRODUCTIONID AND
Price.levelId = Price_level.levelId AND
Booking.bookingId (+) = t.bookingId AND
Customer.customerId = Booking.customerId AND
ccons.cConcessionId (+) = Customer.cConcessionId AND
Membership.membershipId (+) = t.membershipId AND
Membership.mConcessionId = mcons.mConcessionId
ORDER BY t.ticketId
One potential problem you have is these two conditions:
Booking.bookingId (+) = t.bookingId AND
Customer.customerId = Booking.customerId AND
Since you're doing an outer join to Booking, its columns will appear as NULL when no match is found; but then your doing a normal join to Customer, so those rows will be eliminated since NULL cannot be equal to anything. You may want to change the second line to an outer join as well.
But, I don't know if that's your primary problem, since I don't actually understand exactly what you're asking. What do you mean by "NULL value of the foreign key"? You haven't specified what your foreign keys are.
To expand on Dave's observation, and to give you an example of SQL92 syntax, please please please learn it and get away from Oracle's own outer join syntax.
FROM
TICKET t
JOIN Performance per
ON per.performance_id = t.performance_id
JOIN Production pro
ON pro.produciton_id = t.production_id
JOIN PRICE pr
ON pr.production_id = pro.production_id
AND pr.levelId = t.level_id
JOIN price_level pl
ON pl.levelid = pr.levelid
LEFT OUTER JOIN booking b
on b.booking_id = t.booking_id
LEFT OUTER JOIN customer cus
on cus.customer_id = b.customer_id
LEFT OUTER JOIN customer_concession cons
ON cons.concession_id = cus.concession_id
LEFT OUTER JOIN memebership m
ON M.membership_id = t.membership_id
LEFT OUTER JOIN membership_concession mc
ON mc.mConcession_id = m.mConcession_id
Order by t.ticketid

Resources