Can this Oracle SQL query be simplified? - sql

Is there a way I can write this better? The way it's currently written is taking a long time to pull the data. The results of the data also repeat data multiple lines with the same info. Any suggestions? I tried changing the join clauses but that didn't help much. I'm not sure what else I could use to shorten the query to make it run smoother and get better results.
select
PT_IDENTIFIER.PT_IDENTIFIER_VALUE,
PT_STUDY.FK_SOCRD_ID,
patient.PTLASTNAME || ', ' || patient.PTFIRSTNAME as "Patient name",
patient.DOB,
PT_STUDY.SUBJECT_NUMBER,
CR_imaging.CR_IMAGING as "CR_Imaging",
CR_imaging.CR_IMAGING_SPEC,
CR_IMAGING.CR_IMAGING_DT,
CR_imaging.CR_IMG_SITE,
CR_IMAGING.CR_IMG_SITE_SPEC,
CR_IMAGING.CR_IMAGING_CT,
CR_IMAGING.CR_IMAGING_CN,
CR_IMAGING.CR_IMAGING_CM,
CR_WORKUPPROC.CR_WORKUPPROC,
CR_WORKUPPROC.CR_WORKUPPROC_DT,
CR_DISEASE_HISTORY.CR_DISEASE_HISTORY,
CR_DISEASE_HISTORY.CR_DISEASE_HISTORY_DT,
CR_MDT.CR_MDT_DT,
CR_MDT.CR_MDT_DIAG,
CR_MDT.CR_MDT_PHYS,
CR_MDT.CR_MDT_PRESENTED,
CR_MDT.CR_MDT_HISTTYPE,
CR_MDT.CR_MDT_STAGE,
CR_MDT.CR_MDT_CT,
CR_MDT.CR_MDT_CN,
CR_MDT.CR_MDT_CM,
CR_MDT.CR_MDT_PT,
CR_MDT.CR_MDT_PN,
CR_MDT.CR_MDT_PM,
CR_MDT.CR_MDT_LOOKBACK,
CR_MDT_PATH_REVIEW_DT,
CR_MDT_PATH_REVIEW,
CR_MDT_RECOM.CR_MDT_RECOM,
CR_MDT_RECOM.CR_MDT_RECOM_SPEC,
TUMORSITE.DIAGNOSIS_DT,
TUMORSITE.TUMORSITE,
TUMORSITE.TUMORSITE_SPEC,
TUMORSITE.RECURRENCE_DT,
TUMORSITE.RECURRENCE_DT_EST,
TUMORSITE.METASTASIS_DT,
TUMORSITE.METASTASIS_DT_EST,
CR_SYSTEMIC.CR_AGENT,
CR_SYSTEMIC.CR_AGENT_SPEC,
CR_SYSTEMIC.CR_SYS_CYCLE,
CR_SYSTEMIC.CR_SYS_DOSE_DAY,
CR_SYSTEMIC.CR_SYS_DOSE_TOTAL,
CR_SYSTEMIC.CR_SYS_START_DT,
CR_SYSTEMIC.CR_SYS_START_DT_EST,
CR_SYSTEMIC.CR_SYS_END_DT,
CR_SYSTEMIC.CR_SYS_END_DT_EST,
CR_RADIATION.CR_RAD_START_DT,
CR_RADIATION.CR_RAD_START_DT_EST,
CR_RADIATION.CR_RAD_END_DT,
CR_RADIATION.CR_RAD_END_DT_EST,
CR_RADIATION.CR_RAD_PHYS,
CR_RADIATION.CR_RAD_DOSE,
CR_RADIATION.CR_RAD_NOTES,
CR_SURGERY.CR_SURGERY_DT,
CR_SURGERY.CR_SURGERY,
CR_SURGERY.CR_SURGEON,
CR_SURGERY.CR_SURGERY_DT_EST,
CR_SURGERY.CR_SURG_APPROACH,
CR_SURGERY.CR_SURGERY_SPEC,
CR_PATHOLOGY.CR_SURG_PT,
CR_PATHOLOGY.CR_SURG_PN,
CR_PATHOLOGY.CR_SURG_PM,
CR_PATHOLOGY.CR_SURG_HISTTYPE,
CR_PATHOLOGY.CR_SURG_TME,
CR_PATHOLOGY.CR_SURG_TME_REASON,
CR_PATHOLOGY.CR_SURG_TME_REASON_SPEC,
CR_PATHOLOGY.CR_SURG_DISTAL,
CR_PATHOLOGY.CR_SURG_MSI,
CR_PATHOLOGY.CR_SURG_CRM,
CR_PATHOLOGY.CR_SURG_PROX_DIST,
FU_STATUS.FU_DT,
FU_STATUS.FU_STATUS,
FU_STATUS.FU_CANCERSTATUS,
CR_LAB.CR_LAB_DT,
CR_LAB_TUMORMARKER.CR_LAB_TUMORMARKER,
CR_DISEASE_HISTORY.CR_FAM_HISTORY,
CR_GENTEST.CR_GENTEST,
CR_GENTEST.CR_GENTEST_SPEC,
CR_GENTEST.CR_GENTEST_DT,
CR_GENTEST.CR_GENTEST_RESULT
from
CR_IMAGING
left join patient
on CR_IMAGING.fk_SOCRD_ID=patient.SOCRD_ID
left join PT_IDENTIFIER
on patient.socrd_id=PT_IDENTIFIER.FK_SOCRD_ID
left join PT_STUDY
on patient.SOCRD_ID=PT_STUDY.FK_SOCRD_ID
left join CR_DISEASE_HISTORY
on CR_DISEASE_HISTORY.FK_SOCRD_ID=patient.SOCRD_ID
left join CR_MDT
on CR_MDT.FK_SOCRD_ID=PATIENT.SOCRD_ID
left join CR_MDT_RECOM
on CR_MDT.CR_MDT_ID=CR_MDT_RECOM.FK_CR_MDT_ID
left join tumorsite
on tumorsite.FK_SOCRD_ID=PATIENT.SOCRD_ID
left join CR_SYSTEMIC
on CR_SYSTEMIC.FK_SOCRD_ID=PATIENT.SOCRD_ID
left join CR_RADIATION
on CR_RADIATION.FK_SOCRD_ID=PATIENT.SOCRD_ID
left join CR_SURGERY
on CR_SURGERY.FK_SOCRD_ID=PATIENT.SOCRD_ID
LEFT JOIN FU_STATUS
ON FU_STATUS.FK_SOCRD_ID=PATIENT.SOCRD_ID
LEFT JOIN CR_LAB
ON CR_LAB.FK_SOCRD_ID=PATIENT.SOCRD_ID
LEFT JOIN CR_LAB_TUMORMARKER
ON CR_LAB_TUMORMARKER.FK_CR_LAB_ID=CR_LAB.CR_LAB_ID
left join CR_PATHOLOGY
on CR_PATHOLOGY.FK_CR_SURGERY_ID=CR_SURGERY.CR_SURGERY_ID,
cr_workupproc CR_WORKUPPROC
where cr_workupproc.FK_SOCRD_ID=patient.SOCRD_ID
and CR_DISEASE_HISTORY.FK_SOCRD_ID=patient.SOCRD_ID
and PT_STUDY=3
GROUP BY PT_STUDY.SUBJECT_NUMBER,
patient.PTLASTNAME, patient.PTFIRSTNAME,
CR_imaging.CR_IMAGING,
CR_IMAGING.CR_IMAGING_DT, patient.DOB,
CR_imaging.CR_IMG_SITE,
CR_IMAGING.CR_IMG_SITE_SPEC,
CR_imaging.CR_IMAGING_SPEC,
CR_IMAGING.CR_IMAGING_CT,
CR_IMAGING.CR_IMAGING_CN,
CR_IMAGING.CR_IMAGING_CM,
CR_WORKUPPROC.CR_WORKUPPROC,
CR_WORKUPPROC.CR_WORKUPPROC_DT,
CR_DISEASE_HISTORY.CR_DISEASE_HISTORY,
CR_DISEASE_HISTORY.CR_DISEASE_HISTORY_DT,
CR_MDT_RECOM.CR_MDT_RECOM,
CR_MDT.CR_MDT_DT,
CR_MDT.CR_MDT_PHYS,
CR_MDT.CR_MDT_PRESENTED,
CR_MDT.CR_MDT_HISTTYPE,
CR_MDT.CR_MDT_STAGE,
CR_MDT.CR_MDT_CT,
CR_MDT.CR_MDT_CN,
CR_MDT.CR_MDT_CM,
CR_MDT.CR_MDT_LOOKBACK,
CR_MDT.CR_MDT_PT,
CR_MDT.CR_MDT_PN,
CR_MDT.CR_MDT_PM,
CR_MDT_PATH_REVIEW_DT,
CR_MDT_PATH_REVIEW,
TUMORSITE.TUMORSITE,
TUMORSITE.TUMORSITE_SPEC,
TUMORSITE.RECURRENCE_DT,
TUMORSITE.RECURRENCE_DT_EST,
TUMORSITE.METASTASIS_DT,
TUMORSITE.METASTASIS_DT_EST,
CR_SYSTEMIC.CR_AGENT,
CR_SYSTEMIC.CR_AGENT_SPEC,
CR_SYSTEMIC.CR_SYS_CYCLE,
CR_SYSTEMIC.CR_SYS_DOSE_DAY,
CR_SYSTEMIC.CR_SYS_DOSE_TOTAL,
CR_SYSTEMIC.CR_SYS_START_DT,
CR_SYSTEMIC.CR_SYS_START_DT_EST,
CR_SYSTEMIC.CR_SYS_END_DT,
CR_SYSTEMIC.CR_SYS_END_DT_EST,
CR_RADIATION.CR_RAD_START_DT,
CR_RADIATION.CR_RAD_START_DT_EST,
CR_RADIATION.CR_RAD_END_DT,
CR_RADIATION.CR_RAD_END_DT_EST,
CR_RADIATION.CR_RAD_PHYS,
CR_RADIATION.CR_RAD_DOSE,
CR_RADIATION.CR_RAD_NOTES,
CR_SURGERY.CR_SURGERY_DT,
CR_SURGERY.CR_SURGERY,
CR_SURGERY.CR_SURGEON,
CR_SURGERY.CR_SURGERY_DT_EST,
CR_SURGERY.CR_SURG_APPROACH,
CR_PATHOLOGY.CR_SURG_PT,
CR_PATHOLOGY.CR_SURG_PN,
CR_PATHOLOGY.CR_SURG_PM,
CR_PATHOLOGY.CR_SURG_HISTTYPE,
CR_PATHOLOGY.CR_SURG_TME,
CR_PATHOLOGY.CR_SURG_TME_REASON,
CR_PATHOLOGY.CR_SURG_TME_REASON_SPEC,
CR_PATHOLOGY.CR_SURG_DISTAL,
CR_PATHOLOGY.CR_SURG_MSI,
CR_PATHOLOGY.CR_SURG_CRM,
CR_PATHOLOGY.CR_SURG_PROX_DIST,
PT_STUDY.FK_SOCRD_ID,
CR_MDT.CR_MDT_DIAG,
FU_STATUS.FU_DT,
FU_STATUS.FU_STATUS,
FU_STATUS.FU_CANCERSTATUS,
PT_IDENTIFIER_VALUE,
CR_MDT_RECOM.CR_MDT_RECOM_SPEC,
TUMORSITE.DIAGNOSIS_DT,
CR_LAB.CR_LAB_DT,
CR_LAB_TUMORMARKER.CR_LAB_TUMORMARKER,
CR_SURGERY.CR_SURGERY_SPEC

difficult to say without knowing more about your tables and data.
Its probably better (if only for readability) not to mix your join methods, so i'd convert the inner join to
inner join cr_workupproc on cr_workupproc.FK_SOCRD_ID=patient.SOCRD_ID
and CR_DISEASE_HISTORY.FK_SOCRD_ID
your only filter in the query is
and PT_STUDY=3
but pt_study seems to be a table or is this also a column on some table? if so its probably better to be explicit as to where it is with a table qualifier.
If this is not a column on cr_imaging table, then you probably need to check your table order, as you are probably doing a number of full table scans.
Also you should get an explain plan for the query to see what it is doing which may help you to optimise the query.

Related

What are the possible ways to optimize the below postgreSQL code?

I have written this SQL query to fetch the data from greenplum datalake. The primary table has hardy 800,000ish rows which I am joining with other table. The below query is taking insane amount of time to give result. What might be the possible reason for the longer query time? How to resolve it?
select
a.pole,
t.country_name,
a.service_area,
a.park_name,
t.turbine_platform_name,
a.turbine_subtype,
a.pad as "turbine_name",
t.system_number as "turbine_id",
a.customer,
a.service_contract,
a.component,
c.vendor_mfg as "component_manufacturer",
a.case_number,
a.description as "case_description",
a.rmd_diagnosis as "case_rmd_diagnostic_description",
a.priority as "case_priority",
a.status as "case_status",
a.actual_rootcause as "case_actual_rootcause",
a.site_trends_feedback as "case_site_feedback",
a.added as "date_case_added",
a.start as "date_case_started",
a.last_flagged as "date_case_flagged_by_algorithm_latest",
a.communicated as "date_case_communicated_to_field",
a.field_visible_date as "date_case_field_visbile_date",
a.fixed as "date_anamoly_fixed",
a.expected_clse as "date_expected_closure",
a.request_closure_date as "date_case_request_closure",
a.validation_date as "date_case_closure",
a.production_related,
a.estimated_value as "estimated_cost_avoidance",
a.cms,
a.anomaly_category,
a.additional_information as "case_additional_information",
a.model,
a.full_model,
a.sent_to_field as "case_sent_to_field"
from app_pul.anomaly_stage a
left join ge_cfg.turbine_detail t on a.scada_number = t.system_number and a.added > '2017-12-31'
left join tbwgr_v.pmt_wmf_tur_component_master_t c on a.component = c.component_name
Your query is basically:
select . . .
from app_pul.anomaly_stage a left join
ge_cfg.turbine_detail t
on a.scada_number = t.system_number and
a.added > '2017-12-31' left join
tbwgr_v.pmt_wmf_tur_component_master_t c
on a.component = c.component_name
First, the condition on a is ignored, because it is the first table in the left join and is the on clause. So, I assume you actually intend for it to filter, so write the query as:
select . . .
from app_pul.anomaly_stage a left join
ge_cfg.turbine_detail t
on a.scada_number = t.system_number left join
tbwgr_v.pmt_wmf_tur_component_master_t c
on a.component = c.component_name
where a.added > '2017-12-31'
That might help with performance. Then in Postgres, you would want indexes on turbine_detail(system_number) and pmt_wmf_tur_component_master_t(component_name). It is doubtful that an index would help on the first table, because you are already selecting a large amount of data.
I'm not sure if indexes would be appropriate in Greenplum.
Verify if the joins are using respective primary and foreign keys.
Try to execute the query removing one left join after the other, so you see the focus the problem.
Try using the plan execution.

Sql Inner join query on condition when specific value

I have following query:
SELECT Art.Id, Art.Nummer, Art.Serie, Art.EANBarcode, Art.Preis, Art.Volumen, Art.Vater, Art.Name, Art.Amazon, Kat.Name, Subkat.Name, Subsubkat.Name FROM
tbArtikel As Art
INNER JOIN tbKategorie As Kat ON Art.FK_Kategorie_ID=Kat.Id
INNER JOIN tbSubkategorie As Subkat ON Art.FK_SubKategorie_ID=Subkat.Id
INNER JOIN tbSubsubkategorie As Subsubkat ON Art.FK_SubSubKategorie_ID=Subsubkat.Id
WHERE RIGHT(Art.Nummer,2)='.1'
The situation is that Art.FK_SubSubKategorie_ID can be null (developers did that setting 0 instead of null) - knows that bad habit but how it is. However i want to make if there is really 0 for Art.FK_SubSubKategorie_ID i want to take that record and for Subsubkat.Name just put empty string. Hope got my point.
Additional question if possible(PS):
Is there any diffrence in where condition if i do:
WHERE RIGHT(Art.Nummer,2)='.1'
WHERE Art.Nummer LIKE '%.1'
or even:
WHERE NOT RIGHT(Art.Nummer,2)='.1'
WHERE Art.Nummer NOT LIKE '%.1'
I know that like working with indexes, but i am just talking about whether in this case both will work and search exactly the same? I am using that to get specific articles.
Try this;
SELECT Art.Id, Art.Nummer, Art.Serie,
Art.EANBarcode, Art.Preis, Art.Volumen, Art.Vater, Art.Name,
Art.Amazon, Kat.Name, Subkat.Name, ISNULL(Subsubkat.Name,'')
FROM
tbArtikel As Art
INNER JOIN tbKategorie As Kat ON Art.FK_Kategorie_ID=Kat.Id
INNER JOIN tbSubkategorie As Subkat ON Art.FK_SubKategorie_ID=Subkat.Id
LEFT OUTER JOIN tbSubsubkategorie As Subsubkat ON Art.FK_SubSubKategorie_ID=Subsubkat.Id
WHERE RIGHT(Art.Nummer,2)='.1'

Access SQL query without duplicate results

I made a query and wanted to not have any duplicates but i got some times 3 duplicates and when i used DISTINCT or DISTINCTROW i got only 2 duplicates.
SELECT f.flight_code,
f.status,
a.airport_name,
a1.airport_name,
f.departing_date+f.departing_time AS SupposedDepartingTime,
f.landing_date+f.landing_time AS SupposedLandingTime,
de.actual_takeoff_date+de.actual_takeoff_time AS ActualDepartingTime,
SupposedLandingTime+(ActualDepartingTime-SupposedDepartingTime) AS ActualLandingTime
FROM
(((Flights AS f
LEFT JOIN Aireports AS a
ON a.airport_code = f.depart_ap)
LEFT JOIN Aireports AS a1
ON f.target_ap = a1.airport_code)
LEFT JOIN Irregular_Events AS ie
ON f.flight_code = ie.flight_code)
LEFT JOIN Delay_Event AS de
ON ie.IE_code = de.delay_code;
had to use LEFT JOIN because when i used INNER JOIN i missed some of the things i wanted to show because i wanted to see all the flights and not only the flights that got delayed or canceled.
This is the results when i used INNER JOIN, you can see only the flights that have the status "ביטול" or "עיכוב" and that is not what i wanted.
[the results with LEFT JOIN][2]
[2]: https://i.stack.imgur.com/cgE2G.png
and when i used DISTINCT where you see the rows with the NUMBER 6 on the first column it appear only two times
IMPORTANT!
I just checked my query and all the tables i use there and i saw my problem but dont know how to fix it!
in the table Irregular_Events i have more the one event for flights 3,6 and 8 and that is why when i use LEFT JOIN i see more even thou i use distinct, please give me some help!
Not entirely sure without seeing the table structure, but this might work:
SELECT f.flight_code,
f.status,
a.airport_name,
a1.airport_name,
f.departing_date+f.departing_time AS SupposedDepartingTime,
f.landing_date+f.landing_time AS SupposedLandingTime,
de.actual_takeoff_date+de.actual_takeoff_time AS ActualDepartingTime,
SupposedLandingTime+(ActualDepartingTime-SupposedDepartingTime) AS ActualLandingTime
FROM
((Flights AS f
LEFT JOIN Aireports AS a
ON a.airport_code = f.depart_ap)
LEFT JOIN Aireports AS a1
ON f.target_ap = a1.airport_code)
LEFT JOIN
(
SELECT
ie.flight_code,
de1.actual_takeoff_date,
de1.actual_takeoff_time
FROM
Irregular_Events ie
INNER JOIN Event AS de1
ON ie.IE_code = de1.delay_code
) AS de
ON f.flight_code = de.flight_code
It is hard to tell what is the problem with your query without any sample of the output, and without any description of the structure of your tables.
But your problem is that your are querying from the flights table, which [I assume] can be linked to multiple irregular_events, which can possibly also be linked to multiple delay_event.
If you want to get only one row per flight, you need to make sure your joins return only one row too. Maybe you can do it by adding one more condition to the join, or by adding a condition in a sub-query.
EDIT
You could try to add a GROUP BY to the query:
GROUP BY
f.flight_code,
f.status,
a.airport_name,
a1.airport_name;

Best way to optimize this SQL Query

I have to optimize this query and I am really in a hurry here. The following query searches by client. The input value RIF.keyvaluechar
LIKE 'V%10553790 ' is because in some old registers in the database some IDs when missing characters it used to be V0012345678 but it should have been V12345678 as that's the maximum amount of characters the ID can have. I know 12345678 should have been numeric and the V a char and then compare, but that's another issue.
Anyway, the query is this one:
SELECT DISTINCT idata.itemnum AS [ID],
LTRIM(RTRIM(ISNULL(CONTRATO.keyvaluechar,'N/A'))) AS [Contrato],
idata.datestored AS [Fecha],
NUMERO.keyvaluesmall AS [Numero],
TIPO.keyvaluechar AS [Tipo],
LTRIM(RTRIM(ISNULL(LC.lifecyclename,'N/A'))) AS [Flujo],
LTRIM(RTRIM(ISNULL(LC.lcnum,-1))) AS [FlujoID],
LTRIM(RTRIM(ISNULL(LCS.statename,'N/A'))) AS [Cola],
LTRIM(RTRIM(ISNULL(LCS.statenum,-1))) AS [ColaID],
CASE
WHEN PC.NombreProceso IN('PTD','PV2','PV3') THEN 1
ELSE 0
END AS [Portada]
FROM OnBase.hsi.itemdata idata WITH (NOLOCK)
INNER JOIN OnBase.hsi.keyitem109 TIPO WITH (NOLOCK) ON TIPO.itemnum = idata.itemnum
INNER JOIN OnBase.hsi.keyitem113 NUMERO WITH (NOLOCK) ON NUMERO.itemnum = idata.itemnum
LEFT JOIN OnBase.hsi.keyitem132 CONTRATO WITH (NOLOCK) ON CONTRATO.itemnum = idata.itemnum
LEFT JOIN OnBase.hsi.keyitem114 CLIENTE WITH (NOLOCK) ON CLIENTE.itemnum = idata.itemnum
LEFT JOIN OnBase.hsi.keyitem111 RIF WITH (NOLOCK) ON RIF.itemnum = idata.itemnum
INNER JOIN OnBase.hsi.doctype DOC WITH (NOLOCK) ON DOC.itemtypenum = idata.itemtypenum
INNER JOIN BD_WorkFlow.dbo.BBVA_ProcesosConfig PC WITH (NOLOCK) ON PC.ID_Documento = idata.itemtypenum
LEFT JOIN Onbase.hsi.itemlc ILC WITH (NOLOCK) ON ILC.itemnum = idata.itemnum
LEFT JOIN Onbase.hsi.lcstate LCS WITH (NOLOCK) ON LCS.statenum = ILC.statenum
LEFT JOIN Onbase.hsi.lifecycle LC WITH (NOLOCK) ON LC.lcnum = ILC.lcnum
WHERE PC.NombreProceso <> 'XXX' AND
PC.NombreProceso NOT IN('PTD','PV2','PV3') AND
TIPO.keyvaluechar = 'CCD' AND
RIF.keyvaluechar LIKE 'V%10553790 '
As you can see it is this way so it finds V0012345678 or V12345678 but this is not the right way or I feel it is the best optimization, although I am no expert in databases.
Anyways, I've though about something like this instead of last line
AND LEFT ('RIF.Keyvaluechar, 1) ="V"
AND SUBSTRING (RIF.Keyvaluechar, 2, LEN(RIF.Keyvaluechar)) = "12345678"
What do you guys think? Is there any other better way to improve upon this?
First, your query has a logic problem. You have this:
LEFT JOIN OnBase.hsi.keyitem111 RIF WITH(NOLOCK) ON RIF.itemnum = idata.itemnum
and then this in your where clause:
AND RIF.keyvaluechar LIKE 'V%10553790 '
Putting that filter in your where clause effectively changes your left join to an inner join. To fix this, move the filter to the join.
In terms of optimizing it, I assume that means to make it run faster. What you were thinking about will probably slow things down because you are filtering on function results instead of fields. A better approach, no matter how much of a hurry you are in, is to look at the indexes in your database and try to filter on those. In fact, it might be appropriate to add new ones.
Is the Keyvaluechar always a number from the second character onwards and you want to treat it as a number (=remove leading zeros). You could try to add a persisted column convert(int, SUBSTRING (Keyvaluechar, 2, 10)) to the table, then index that, and use it as a search criteria. At least I would assume that should help a lot.
In addition to that, looking at statistics IO output might be a good idea too, to see what table is actually responsible for the biggest I/O amounts.
Just a note, I hope you also know the problems using NOLOCK can cause you.

Ignore null values in select statement

I'm trying to retrieve a list of components via my computer_system, BUT if a computer system's graphics card is set to null (I.e. It has an onboard), the row isn't returned by my select statement.
I've been trying to use COALESCE without results. I've also tried with and OR in my WHERE clause, which then just returns my computer system with all different kinds of graphic cards.
Relevant code:
SELECT
computer_system.cs_id,
computer_system.cs_name,
motherboard.name,
motherboard.price,
cpu.name,
cpu.price,
gfx.name,
gfx.price
FROM
public.computer_case ,
public.computer_system,
public.cpu,
public.gfx,
public.motherboard,
public.ram
WHERE
computer_system.cs_ram = ram.ram_id AND
computer_system.cs_cpu = cpu.cpu_id AND
computer_system.cs_mb = motherboard.mb_id AND
computer_system.cs_case = computer_case.case_id AND
computer_system.cs_gfx = gfx.gfx_id; <-- ( OR computer_system.cs_gfx IS NULL)
Returns:
1;"Computer1";"Fractal Design"; 721.00; "MSI Z87"; 982.00; "Core i7 I7-4770K "; 2147.00; "Crucial Gamer"; 1253.00; "ASUS GTX780";3328.00
Should I use Joins? Is there no easy way to say return the requested row, even if there's a bloody NULL value. Been struggling with this for at least 2 hours.
Tables will be posted if needed.
EDIT: It should return a second row:
2;"Computer2";"Fractal Design"; 721.00; "MSI Z87"; 982.00; "Core i7 I7-4770K "; 2147.00; "Crucial Gamer"; 1253.00; "null/nothing";null/nothing
You want a LEFT OUTER JOIN.
First, clean up your code so you use ANSI joins so it's readable:
SELECT
computer_system.cs_id,
computer_system.cs_name,
motherboard.name,
motherboard.price,
cpu.name,
cpu.price,
gfx.name,
gfx.price
FROM
public.computer_system
INNER JOIN public.computer_case ON computer_system.cs_case = computer_case.case_id
INNER JOIN public.cpu ON computer_system.cs_cpu = cpu.cpu_id
INNER JOIN public.gfx ON computer_system.cs_gfx = gfx.gfx_id
INNER JOIN public.motherboard ON computer_system.cs_mb = motherboard.mb_id
INNER JOIN public.ram ON computer_system.cs_ram = ram.ram_id;
Then change the INNER JOIN on public.gfx to a LEFT OUTER JOIN:
LEFT OUTER JOIN public.gfx ON computer_system.cs_gfx = gfx.gfx_id
See PostgreSQL tutorial - joins.
I very strongly recommend reading an introductory tutorial to SQL - at least the PostgreSQL tutorial, preferably some more material as well.
It looks like it's just a bracket placement issue. Pull the null check and the graphics card id comparison into a clause by itself.
...
computer_system.cs_case = computer_case.case_id AND
(computer_system.cs_gfx IS NULL OR computer_system.cs_gfx = gfx.gfx_id)
Additionally, you ask if you should use joins. You are in fact using joins, by virtue of having multiple tables in your FROM clause and specifying the join criteria in the WHERE clause. Changing this to use the JOIN ON syntax might be a little easier to read:
FROM sometable A
JOIN someothertable B
ON A.somefield = B.somefield
JOIN somethirdtable C
ON A.somefield = C.somefield
etc
Edit:
You also likely want to make the join where you expect the null value to be a left outer join:
SELECT * FROM
first_table a
LEFT OUTER JOIN second_table b
ON a.someValue = b.someValue
If there is no match in the join, the row from the left side will still be returned.