2009-05-13 17 views
7

Dadas estas dos tablas:Prevenir Oracle menos el comunicado de la eliminación de duplicados

CREATE TABLE TEST1 (TEST VARCHAR2(1 BYTE)) 
CREATE TABLE TEST2 (TEST VARCHAR2(1 BYTE)) 

Dónde PRUEBA1 tiene dos filas tanto con el valor 'A' y TEST2 tiene una fila con el valor 'B'.

Cuando ejecuto este comando:

SELECT TEST FROM TEST1 
MINUS 
SELECT TEST FROM TEST2 

me sale la salida:

Test 
----- 
A 

Parece que MENOS elimina los duplicados (ya que hay dos filas 'A' en PRUEBA1).

¿Cómo se puede obtener MENOS consulta para incluir valores duplicados (devolver dos filas 'A')?

Respuesta

0

Oracle es compatible con múltiples columnas de la instrucción IN, para que pueda escribir:

SELECT a, b, c 
FROM table1 
WHERE (a,b,c) not in (
    select a,b,c from table2 
) 
0

el modificador ALL hace que UNION devuelva todas las filas (por ejemplo, UNION ALL), ¿quizás se puede aplicar a MINUS? Como en

select field1 from table1 
minus all 
select field2 from table2 
+0

No puedo, tengo miedo – cagcowboy

+0

No. Eso tendría mucho sentido;) –

0

Parte de lo que hace menos es eliminar duplicados. Considere usar NOT IN para evitar eliminar duplicados.

SELECT TEST FROM TEST1 WHERE TEST NOT IN(SELECT TEST FROM TEST2) 
1
SELECT field1 FROM table1 WHERE field1 NOT IN (SELECT field2 FROM table2) 

funcionara, entonces siempre que campo2 no puede contener valores nulos.

+0

Lo único es que, en realidad, la afirmación menos que estoy usando selecciona más que el único campo (selecciona 10 campos). –

+0

Puede hacer esto con múltiples columnas también ...DÓNDE (a, b) NO EN (SELECCIONE x, y DESDE la tabla2) –

7

Otra opción:

SELECT TEST, row_number() OVER (PARTITION BY TEST ORDER BY TEST) FROM TEST1 
MINUS 
SELECT TEST, row_number() OVER (PARTITION BY TEST ORDER BY TEST) FROM TEST2 

esto sería MENOS con cada duplicado tratada como una entrada distinta. Tenga en cuenta que en el ejemplo siguiente, si TEST1 tiene dos valores "C" y TEST2 solo tiene uno, obtendrá uno en la salida.

dev> select * from test1; 

T 
- 
A 
A 
B 
C 
C 

dev> select * from test2; 

T 
- 
B 
C 

dev>  SELECT TEST, row_number() OVER (PARTITION BY TEST ORDER BY TEST) FROM TEST1 
    2  MINUS 
    3  SELECT TEST, row_number() OVER (PARTITION BY TEST ORDER BY TEST) FROM TEST2 
    4/

T ROW_NUMBER()OVER(PARTITIONBYTESTORDERBYTEST) 
- -------------------------------------------- 
A           1 
A           2 
C           2 
1

El "NO EN" respuestas son los correctos. Una alternativa, que podría ser más fácil para algunos escenarios, es el "NO EXISTE" operador:

SELECT TEST FROM TEST1 
WHERE NOT EXISTS 
(SELECT null FROM TEST2 WHERE TEST2.TEST = TEST1.TEST); 

(Nota: el "nulo" en la cláusula select no tiene sentido aquí)

yo personalmente utilizar ambos métodos , pero me gusta el NO EXISTE a menudo porque es más flexible, por ejemplo, no requiere que la comparación esté en una condición de igualdad.

Las versiones recientes del optimizador a menudo convertirán un NO EN un NO EXISTE, o viceversa; Sin embargo, si tiene una versión anterior (por ejemplo, 8i o incluso 9i, creo), puede ver los beneficios de rendimiento al cambiar entre estos dos métodos.

0
SELECT TEST FROM TEST1 WHERE TEST IN(
SELECT TEST FROM TEST1 
MINUS 
SELECT TEST FROM TEST2); 
+0

Explique cómo su respuesta resuelve el problema, ayudará a todos a comprender su solución con más claridad y para referencia futura. – Aziz

Cuestiones relacionadas