2010-03-28 20 views
19

Mi pregunta es bastante similar a Restricting a LEFT JOIN, con una variación.Eliminar duplicados de IZQUIERDA UNIÓN EXTERNA

Suponiendo que tengo una tabla SHOP y otra tabla UBICACIÓN. La ubicación es una especie de tabla secundaria de la tabla SHOP, que tiene dos columnas de interés, una es una clave de división (llamándola simplemente KEY) y un número de "SHOP". Esto coincide con el Número "NO" en la tabla SHOP.

probé este externa izquierda:

SELECT S.NO, L.KEY 
FROM SHOP S 
LEFT OUTER JOIN LOCATN L ON S.NO = L.SHOP 

pero yo estoy haciendo una gran cantidad de duplicados, ya que hay muchos lugares que pertenecen a una sola tienda. Quiero eliminarlos y solo obtener una lista de entradas de "compras, llaves" sin duplicados.

los datos son correctos, pero los duplicados aparecen como sigue:

SHOP  KEY 
1  XXX 
1  XXX 
2  YYY 
3  ZZZ 
3  ZZZ etc. 

Me gustaría que los datos que aparecerá de esta forma:

SHOP  KEY 
1  XXX 
2  YYY 
3  ZZZ etc. 

mesa SHOP:

NO 
1  
2  
3  

UBICACIÓN tabla:

LOCATION SHOP KEY 
    L-1  1 XXX 
    L-2  1 XXX 
    L-3  2 YYY 
    L-4  3 YYY 
    L-5  3 YYY 

(Oracle Database 10g)

+0

No debería recibir ningún duplicado, aunque, como dijo, puede obtener más de una clave para una tienda si tiene más de un registro de ubicación para la tienda. Por favor explique o dé un ejemplo de lo que quiere decir con "duplicado". –

+1

@Marcus Al principio pensé lo mismo, pero supongo que varias ubicaciones pueden tener la misma clave de división. –

+0

@Marcus & Martin: ah, no creo haber dejado esto en claro. Sí. Varias ubicaciones pueden tener y tienen una misma clave de división. (Estrictamente hablando, divnkey es el padre de la tienda. Así que la jerarquía es como esta Divnkey> Tienda> ubicación). Intento rellenar la tabla de la tienda con los datos de clave de división apropiados. Puede sonar extraño, pero es un proceso de una sola vez y estaba tratando de generar secuencias de comandos de actualización para la tabla SHOP a partir de los datos de la tabla LOCATION, a través de un comando seleccionar 'update shop set divnkey = ....'. No quería complicar la pregunta, así que ponga una simple selección. –

Respuesta

24

Necesitas GROUP BY 'S.No' & 'L.KEY'

SELECT S.NO, L.KEY 
FROM SHOP S 
LEFT OUTER JOIN LOCATN L 
ON S.NO = L.SHOP 
GROUP BY S.NO, L.KEY 
+0

+1 para usar 'GROUP BY' que es equivalente a' DISTINCT' en Oracle http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:32961403234212 pero a veces puede ser más rápido en otros motores, por ejemplo Postgres (usando hash en lugar de ordenar) – vladr

+0

Ok, me acabas de hacer sentir realmente estúpido. Esto funciona perfectamente Gracias. Pero cualquier comentario adicional sobre por qué se requiere el grupo en absoluto cuando se supone que el exterior izquierdo se ocupará de esto. Como en Estoy tratando de entender cómo funciona realmente el izquierdo externo. –

+0

@Kaushik: A LEFT OUTER JOIN no es equivalente ni implica un GROUP BY o DISTINCT. La combinación IZQUIERDA toma todas las filas de la tabla izquierda (primera) y se une a todas las filas de la tabla derecha (segunda) donde se cumple la condición de unión. En una combinación left * outer *, si no se encuentran datos en la tabla correcta que coincida con los datos de la tabla izquierda, los datos de la tabla izquierda aún se devuelven con valores NULL puestos para todos los datos de la tabla derecha. Ninguna agrupación está expresada o implícita. Personalmente, habría usado DISTINCT porque creo que especifica con mayor precisión el intento, pero YMMV. –

7

EDITAR Después de la actualización en su escenario

Creo que debería ser capaz de hacer esto con una simple consulta sub (aunque no he probado esto en contra de una Base de datos Oracle). Algo así como lo siguiente

UPDATE shop s 
SET divnkey = (SELECT DISTINCT L.KEY FROM LOCATN L WHERE S.NO = L.SHOP) 

Lo anterior generará un error en el caso de una tienda de ser asociados con lugares que se encuentran en múltiples divisiones.

Si lo que desea es pasar por alto esta posibilidad y seleccione arbitraria en ese caso se podría utilizar

UPDATE shop s 
SET divnkey = (SELECT MAX(L.KEY) FROM LOCATN L WHERE S.NO = L.SHOP) 
+0

Agradable :) Por eso es importante obtener más de un ángulo. Gracias Martin, su solución definitivamente satisface mi requisito subyacente (pero la otra respuesta específicamente se encarga de eliminar los duplicados, así que tendrá que marcar esa). Cheers –

6

Tuve este problema también pero no pude usar GROUP BY para solucionarlo porque también estaba devolviendo campos de tipo TEXTO. (Lo mismo ocurre con el uso de DISTINCT).

Este código me dio duplica:

select mx.*, case isnull(ty.ty_id,0) when 0 then 'N' else 'Y' end as inuse 
from master_x mx 
left outer join thing_y ty on mx.rpt_id = ty.rpt_id 

me fijo reescribiéndolo así:

select mx.*, 
case when exists (select 1 from thing_y ty where mx.rpt_id = ty.rpt_id) then 'Y' else 'N' end as inuse 
from master_x mx 

Como se puede ver que no se preocupan de los datos dentro de la segunda tabla (thing_y), solo si hubo más de cero coincidencias en el rpt_id dentro de él. (FYI: rpt_id tampoco fue la clave principal en la primera mesa, master_x).

Cuestiones relacionadas