Рассмотрим эти таблицы (стандартный код SQL, работает на 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)
), ...
Желаемый эффект - сортировка таблицы A
по col
по возрастанию, сортировка таблицы B
поcol
по убыванию, затем объединение двух, удаление дубликатов, сохранение порядка перед объединением и выход из таблицы A
результаты в «верху» с таблицей B
в «низе», например (псевдокод)
(
SELECT *
FROM A
ORDER
BY col
)
UNION
(
SELECT *
FROM B
ORDER
BY col DESC
);
Конечно, это не будет работать в SQL, потому что может быть только одно предложение ORDER BY
, и его можно применять только к выражению таблицы верхнего уровня (или какому-либо другому результату запроса SELECT
;Я называю это «набор результатов»).
Первое, на что нужно обратить внимание - это пересечение двух таблиц, в данном случае это значения 4
, 5
и 6
.Способ сортировки пересечения должен быть указан в коде SQL, поэтому желательно, чтобы конструктор также указывал это!(т.е. человек, задающий вопрос, в данном случае).
В этом случае может показаться, что пересечение («дубликаты») должно быть отсортировано в результатах для таблицы A. Следовательно, отсортированный набор результатов должен выглядеть следующим образом:
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
Примечание: в SQL "top" и "bottom" не имеют никакого промежуточного значения, а таблица (кроме результирующего набора) не имеет внутреннего порядка.Также (короче говоря) учтите, что UNION
удаляет повторяющиеся строки косвенно и должно применяться до ORDER BY
.Необходимо сделать вывод, что порядок сортировки каждой таблицы должен быть явно определен путем предоставления столбцов порядка сортировки перед объединением .Для этого мы можем использовать оконную функцию ROW_NUMBER()
, например,
...
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;