UNION joint deux résultats et supprime les doublons, tandis que UNION ALL ne supprime pas les doublons. UNION trie également la sortie finale.
Ce que je veux, c'est l'UNION ALL sans doublons et sans tri. Est-ce possible?
La raison en est que je veux que le résultat de la première requête soit au-dessus du résultat final et la deuxième requête en bas. (Et chacun trié comme s'il était exécuté individuellement)
Je remarque que cette question reçoit beaucoup de vues, je vais donc d'abord répondre à une question que vous n'avez pas posez!
Concernant le titre. Pour obtenir une "union SQL totale avec " distinct "", remplacez simplement UNION ALL
avec UNION
. Cela a pour effet de supprimer les doublons.
Pour votre question spécifique, étant donné la clarification "La première requête doit avoir la" priorité ", donc les doublons doivent être supprimés du bas" vous pouvez utiliser
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
"UNION trie également la sortie finale" - uniquement comme un artefact d'implémentation. C'est par aucun moyen garanti pour effectuer le tri, et si vous avez besoin d'un ordre de tri particulier, vous devez le spécifier avec un ORDER BY
clause. Sinon, l'ordre de sortie est celui qui convient le mieux au serveur.
En tant que tel, votre demande pour une fonction qui exécute un UNION ALL
mais qui supprime les doublons est facile - il s'appelle UNION
.
D'après vos éclaircissements, vous semblez également croire qu'un UNION ALL
renverra tous les résultats de la première requête avant les résultats des requêtes suivantes. C'est aussi non garanti. Encore une fois, la seule façon d'atteindre un ordre particulier est de le spécifier à l'aide d'un ORDER BY
clause.
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;
Mais la vraie réponse est: autre que le ORDER BY
clause, l'ordre de tri sera arbitraire et non garanti.
Considérez ces tables (code SQL standard, s'exécute sur 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)
), ...
L'effet souhaité est le suivant: trier la table A
par col
ascendante, trier la table B
par col
décroissante puis l'union des deux, supprimer les doublons, conserver l'ordre avant l'union et la sortie de la table A
résultats en "haut" avec la table B
en "bas" par exemple (code pesudo)
(
SELECT *
FROM A
ORDER
BY col
)
UNION
(
SELECT *
FROM B
ORDER
BY col DESC
);
Bien sûr, cela ne fonctionnera pas en SQL car il ne peut y avoir qu'une seule clause ORDER BY
Et elle ne peut être appliquée qu'à l'expression de table de niveau supérieur (ou quelle que soit la sortie d'une requête SELECT
est dit: je l'appelle le "jeu de résultats").
La première chose à traiter est l'intersection entre les deux tables, dans ce cas les valeurs 4
, 5
Et 6
. La manière dont l'intersection doit être triée doit être spécifiée dans le code SQL, il est donc souhaitable que le concepteur le spécifie également! (c'est-à-dire la personne qui pose la question, dans ce cas).
L'implication dans ce cas semble être que l'intersection ("doublons") doit être triée dans les résultats du tableau A. Par conséquent, le jeu de résultats trié devrait ressembler à ceci:
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
Remarque en SQL "top" et "bottom" n'a pas de signification inférente et une table (autre qu'un jeu de résultats) n'a pas de classement inhérent. Aussi (pour faire court), considérez que UNION
supprime les lignes en double par implication et doit être appliqué avant ORDER BY
. La conclusion doit être que l'ordre de tri de chaque table doit être explicitement défini en exposant une ou plusieurs colonnes d'ordre de tri avant en cours d'union. Pour cela, nous pouvons utiliser la fonction fenêtrée ROW_NUMBER()
par ex.
...
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;
Essaye ça:
SELECT DISTINCT * FROM (
SELECT column1, column2 FROM Table1
UNION ALL
SELECT column1, column2 FROM Table2
UNION ALL
SELECT column1, column2 FROM Table3
) X ORDER BY Column1
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
Le tri est utilisé pour éliminer les doublons et est implicite pour les requêtes DISTINCT
et UNION
(mais pas UNION ALL
) - vous pouvez toujours spécifier les colonnes que vous préférez classer si vous en avez besoin triées par colonnes spécifiques.
Par exemple, si vous souhaitez trier par les jeux de résultats, vous pouvez introduire une colonne supplémentaire et trier par celle-ci en premier:
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
Je suppose que vos tables sont respectivement table1 et table2, et votre solution est;
(select * from table1 MINUS select * from table2)
UNION ALL
(select * from table2 MINUS select * from table1)