without - Sql Union All*con*"distinto"
union distinct oracle (8)
UNION une dos resultados y elimina duplicados, mientras que UNION ALL no elimina duplicados. UNION también ordena la salida final.
Lo que quiero es UNION ALL sin duplicados y sin la clasificación. ¿Es eso posible?
La razón de esto es que quiero que el resultado de la primera consulta esté por encima del resultado final, y la segunda consulta por debajo. (Y cada uno ordenado como si se ejecutaran individualmente)
"UNION también clasifica el resultado final", solo como un artefacto de implementación. De ninguna manera se garantiza que realice la clasificación, y si necesita un orden particular, debe especificarlo con una cláusula ORDER BY
. De lo contrario, el orden de salida es lo que sea más conveniente para el servidor.
Como tal, su solicitud de una función que ejecute UNION ALL
pero que elimine duplicados es fácil: se llama UNION
.
De su aclaración, también parece creer que un UNION ALL
devolverá todos los resultados de la primera consulta antes que los resultados de las consultas posteriores. Esto tampoco está garantizado. Nuevamente, la única forma de lograr un orden particular es especificarlo usando una cláusula ORDER BY
.
¡Me doy cuenta de que esta pregunta recibe muchas visitas, por lo que primero abordaré una pregunta que no hizo !
Respecto al título. Para lograr un "Sql Union All con " distinto "", simplemente reemplace UNION ALL
con UNION
. Esto tiene el efecto de eliminar duplicados.
Para su pregunta específica, dada la aclaración "La primera consulta debe tener" prioridad ", por lo que los duplicados deben eliminarse de la parte inferior" puede usar
SELECT col1,
col2,
MIN(grp) AS source_group
FROM (SELECT 1 AS grp,
col1,
col2
FROM t1
UNION ALL
SELECT 2 AS grp,
col1,
col2
FROM t2) AS t
GROUP BY col1,
col2
ORDER BY MIN(grp),
col1
1,1: select 1 from dual union all select 1 from dual
1: select 1 from dual union select 1 from dual
Considere estas tablas (código SQL estándar, se ejecuta en SQL Server 2008):
WITH A
AS
(
SELECT *
FROM (
VALUES (1),
(2),
(3),
(4),
(5),
(6)
) AS T (col)
),
B
AS
(
SELECT *
FROM (
VALUES (9),
(8),
(7),
(6),
(5),
(4)
) AS T (col)
), ...
El efecto deseado es este para ordenar la tabla A
por orden ascendente, ordenar la tabla B
por orden descendente y luego unir los dos, eliminar duplicados, mantener el orden antes de la unión y dejar los resultados de la tabla A
en la "parte superior" con la tabla B
en la parte "inferior" ej. (código pesudo)
(
SELECT *
FROM A
ORDER
BY col
)
UNION
(
SELECT *
FROM B
ORDER
BY col DESC
);
Por supuesto, esto no funcionará en SQL porque solo puede haber una cláusula ORDER BY
y solo se puede aplicar a la expresión de la tabla de nivel superior (o cualquiera que sea el resultado de una consulta SELECT
se denomina "conjunto de resultados" ").
Lo primero que hay que abordar es la intersección entre las dos tablas, en este caso los valores 4
, 5
y 6
. La forma en que se debe ordenar la intersección debe especificarse en el código SQL, por lo tanto, ¡es deseable que el diseñador lo especifique también! (es decir, la persona que hace la pregunta, en este caso).
La implicación en este caso parece ser que la intersección ("duplicados") debe ordenarse dentro de los resultados para la tabla A. Por lo tanto, el conjunto de resultados ordenado debe verse así:
VALUES (1), -- A including intersection, ascending
(2), -- A including intersection, ascending
(3), -- A including intersection, ascending
(4), -- A including intersection, ascending
(5), -- A including intersection, ascending
(6), -- A including intersection, ascending
(9), -- B only, descending
(8), -- B only, descending
(7), -- B only, descending
Nota en SQL "arriba" y "abajo" no tiene un significado inferente y una tabla (que no sea un conjunto de resultados) no tiene orden inherente. También (para abreviar una larga historia) considere que UNION
elimina las filas duplicadas por implicación y debe aplicarse antes de ORDER BY
. La conclusión debe ser que el orden de clasificación de cada tabla debe definirse explícitamente al exponer una columna de ordenamiento antes de unirse. Para esto podemos usar la función de ventana ROW_NUMBER()
p. Ej.
...
A_ranked
AS
(
SELECT col,
ROW_NUMBER() OVER (ORDER BY col) AS sort_order_1
FROM A -- include the intersection
),
B_ranked
AS
(
SELECT *,
ROW_NUMBER() OVER (ORDER BY col DESC) AS sort_order_1
FROM B
WHERE NOT EXISTS ( -- exclude the intersection
SELECT *
FROM A
WHERE A.col = B.col
)
)
SELECT *, 1 AS sort_order_0
FROM A_ranked
UNION
SELECT *, 2 AS sort_order_0
FROM B_ranked
ORDER BY sort_order_0, sort_order_1;
La clasificación se usa para eliminar los duplicados, y está implícita para las consultas DISTINCT
y UNION
(pero no UNION ALL
); aún puede especificar las columnas que prefiere ordenar si las necesita ordenadas por columnas específicas.
Por ejemplo, si desea ordenar por conjuntos de resultados, puede introducir una columna adicional y ordenar por ese primero:
SELECT foo, bar, 1 as ResultSet
FROM Foo
WHERE bar = 1
UNION
SELECT foo, bar, 2 as ResultSet
FROM Foo
WHERE bar = 3
UNION
SELECT foo, bar, 3 as ResultSet
FROM Foo
WHERE bar = 2
ORDER BY ResultSet
Supongo que sus tablas son table1 y table2 respectivamente, y su solución es;
(select * from table1 MINUS select * from table2)
UNION ALL
(select * from table2 MINUS select * from table1)
SELECT *, 1 AS sort_order
FROM table1
EXCEPT
SELECT *, 1 AS sort_order
FROM table2
UNION
SELECT *, 1 AS sort_order
FROM table1
INTERSECT
SELECT *, 1 AS sort_order
FROM table2
UNION
SELECT *, 2 AS sort_order
FROM table2
EXCEPT
SELECT *, 2 AS sort_order
FROM table1
ORDER BY sort_order;
Pero la respuesta real es: aparte de la cláusula ORDER BY
, el orden de clasificación será arbitrario y no estará garantizado.
select T.Col1, T.Col2, T.Sort
from
(
select T.Col1,
T.Col2,
T.Sort,
rank() over(partition by T.Col1, T.Col2 order by T.Sort) as rn
from
(
select Col1, Col2, 1 as Sort
from Table1
union all
select Col1, Col2, 2
from Table2
) as T
) as T
where T.rn = 1
order by T.Sort