Вопрос

I've been tasked with writing a query to display report assignments from our company's database. There are three tables I need to query: REPORT, which contains the top-level information of the report, PROCEDURE, which can contain multiple results per report on the individual report procedures, and TECHNICIAN, which can contain multiple technicians per procedure based on who is assigned to it.

My problem is that if there are no technicians assigned to a procedure, it's not returning anything for that procedure, whereas ideally I'd like it to return a row with the technician field being "null".

The current code I have is this:

SELECT
    rep.RPT_ID
    ,tech.TECH_ID
    ,proc.PROC_ID
FROM REPORT rep
LEFT JOIN TECHNICIAN tech ON tech.RPT_ID = rep.RPT_ID
LEFT JOIN PROCEDURE proc ON proc.RPT_ID = rep.RPT_ID
WHERE rep.LAB_ID in ('test_lab')
AND proc.PROC_ID = tech.PROC_ID

I'd like this to return something like this if no tech is assigned:

RPT_ID | TECH_ID | PROC_ID
 12345      456        1
 12345      NULL       2
 67890      123        1
 67890      345        1

But currently I'm not getting that second row.

Это было полезно?

Решение 2

Here is the query.

SELECT
rep.RPT_ID
,tech.TECH_ID
,proc.PROC_ID
FROM REPORT rep
LEFT JOIN TECHNICIAN tech ON tech.RPT_ID = rep.RPT_ID
LEFT JOIN PROCEDURE proc ON proc.RPT_ID = rep.RPT_ID AND proc.PROC_ID = tech.PROC_ID
WHERE rep.LAB_ID in ('test_lab');

Другие советы

The problem is that you have and proc.PROD_ID = tech.PROD_ID in the WHERE clause.

You should move this into the LEFT JOIN of proc

LEFT JOIN PROCEDURE proc ON proc.RPT_ID = rep.RPT_ID and proc.PROD_ID = tech.PROD_ID

Think of it this way, if your query, the SQL joins the tables using the join criteria and then filters the results based on the where clause.

@Janaki's answer only provides PROCEDURE rows if they have a matching TECHNICIAN row. I would assume, in this case, that either the PROCEDURE or the TECHNICIAN could be missing. I would solve this scenario like this:

SELECT rep.rpt_id, tp.tech_id, tp.proc_id
FROM   report rep
       LEFT JOIN
       (SELECT COALESCE (tech.rpt_id, proc.rpt_id) AS rpt_id,
               tech.tech_id,
               proc.proc_id
        FROM   technician tech
               FULL OUTER JOIN procedure proc 
                 ON proc.proc_id = tech.proc_id) tp
          ON tp.rpt_id = rep.rpt_id
WHERE  rep.lab_id IN ('test_lab')

The full outer join ensures that three scenarios are covered: only PROCEDURE; only TECHNICIAN; both PROCEDURE and TECHNICIAN. The LEFT JOIN covers the final scenario: no TECHNICIAN or PROCEDURE.


Given the clarification (see comments), this query can be simplified:

SELECT rep.rpt_id, tech.tech_id, proc.proc_id
FROM   report rep
       LEFT JOIN procedure proc ON proc.rpt_id = rep.rpt_id
       LEFT JOIN technician tech
          ON tech.rpt_id = rep.rpt_id AND proc.proc_id = tech.proc_id
WHERE  rep.lab_id IN ('test_lab');

It's important to join to join to PROCEDURE first, then join TECHNICIAN based on both preceding tables. This allows for the outer joins to cascade as specified by the clarification properly.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top