简体   繁体   中英

Left Outer Join doesn't seem to work properly

I got this piece of sql server 2005 code:

SELECT DT, a.id_uf, hora
FROM CALENDAR c LEFT OUTER JOIN CLIENT_MEDIDAS_COGEN a ON a.fecha_oferta = dt AND a.hora = c.H
WHERE 
(id_tipo_medida IN (6, 1)) AND (id_magnitud = 1) 
AND (DT BETWEEN '10/01/2013' AND '10/01/2013') AND (id_tipo_fact = 3)
ORDER BY DT, a.id_uf, a.hora

On calendar, I have got something like this:

日历

On CLIENT_MEDIDAS_COGEN I have got this:

CLIENT_MEDIDAS_COGEN

And finally, this is the result I am getting:

结果

The question is, how is it possible I'm not getting the rows for hours 1 and 2?? I'm using LEFT OUTER JOIN but it just doesn't seem to work properly.

Thank you so much in advance for your help

Your WHERE clause states that (id_magnitud = 1) . Any rows in Calender that were not joined to CLIENT_MEDIDAS_COGEN will have NULL in the id_magnitude column.

SELECT 
    c.DT, 
    a.id_uf,
    c.hora
FROM 
    CALENDAR c 
    LEFT OUTER JOIN CLIENT_MEDIDAS_COGEN a ON a.fecha_oferta = dt AND a.hora = c.H
WHERE 
    (c.DT BETWEEN '10/01/2013' AND '10/01/2013') 
AND (COALESCE(a.id_tipo_medida, 1) IN (6, 1)) 
AND (COALESCE(a.id_magnitud, 1) = 1) 
AND (COALESCE(a.id_tipo_fact, 3) = 3)
ORDER BY 
    c.DT, a.id_uf, a.hora

Also don't just use the table alias for common columns. Use them for all columns so it's clear where the column resides.

As per MatBaille's comment moving the filters on CLIENT_MEDIDAS_COGEN to the join clause will perform better. The coalesce statments above just give an indication as to the reason for your issue. The below will likely perform better.

SELECT 
    c.DT, 
    a.id_uf,
    c.hora
FROM 
    CALENDAR c 
    LEFT OUTER JOIN CLIENT_MEDIDAS_COGEN a ON 
            a.fecha_oferta = dt 
            AND a.hora = c.H 
            AND (a.id_tipo_medida IN (6, 1)) 
            AND (a.id_magnitud = 1) 
            AND (a.id_tipo_fact = 3)
WHERE 
    (c.DT BETWEEN '10/01/2013' AND '10/01/2013') 
ORDER BY 
    c.DT, a.id_uf, a.hora

That's because of where filters which make it work like inner join. You can move where filters to join conditions, like this:

SELECT c.ID, a.id_uf, c.H
FROM CALENDAR c LEFT OUTER JOIN CLIENT_MEDIDAS_COGEN a ON a.fecha_oferta = dt AND a.hora = c.H
AND 
(a.id_tipo_medida IN (6, 1)) AND (a.id_magnitud = 1) AND (a.id_tipo_fact = 3)
WHERE (DT BETWEEN '10/01/2013' AND '10/01/2013') 
ORDER BY DT, a.id_uf, a.hora

That will make the desired left join effect.

Cleaner (in my opinion) to use a subquery to apply the criteria to the right hand table in the join prior to the LEFT OUTER JOIN.

So it becomes...

SELECT c.ID, a.id_uf, c.H
FROM CALENDAR c 
    LEFT OUTER JOIN 
        (
            SELECt id_uf, hora, fecha_oferta 
            FROM CLIENT_MEDIDAS_COGEN a 
            WHERE (id_tipo_medida IN (6, 1)) AND (id_magnitud = 1) AND (id_tipo_fact = 3)
        ) a ON a.fecha_oferta = dt AND a.hora = c.H

WHERE (DT BETWEEN '10/01/2013' AND '10/01/2013') 
ORDER BY DT, a.id_uf, a.hora

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM