SQL: как использовать UNION и порядок по определенному выбору?

21

У меня есть два выбора:

SELECT id FROM a -- returns 1,4,2,3
UNION
SELECT id FROM b -- returns 2,1

Я получаю правильное количество строк, например: 1,4,2,3 .

Но сначала я хочу получить результаты b table: 2,1,4,3 или 2,1,3,4

Как я могу это сделать?

(Я использую Oracle)

    
задан Topera 17.05.2011 в 22:36
источник

5 ответов

5

Используя советы @Adrian, я нашел решение:

Я использую GROUP BY и COUNT . Я попытался использовать DISTINCT с ORDER BY , но я получаю сообщение об ошибке: "не выражение SELECTed

select id from 
(
    SELECT id FROM a -- returns 1,4,2,3
    UNION ALL -- changed to ALL
    SELECT id FROM b -- returns 2,1
)
GROUP BY id ORDER BY count(id);

Спасибо Adrian и этот блог.

    
ответ дан Topera 17.05.2011 в 23:27
  • Если вы хотите, чтобы строки «b» были первыми, вам не нужен COUNT (id) DESC? Кроме того, это работает только в том случае, если «b» является подмножеством записей в «a». Наконец, вы не можете полагаться на записи из «b» или «a», упорядоченные каким-либо определенным образом, с учетом этого конкретного примера. Когда я попробовал это, я получил 1,2,4,3 для вывода. –  DCookie 18.05.2011 в 00:18
  • a) Да, в этом примере мне нужен DESC (я забыл поставить). Но в моем приложении мне нужно тогда в конце таблицы. b) нет проблем, в моем приложении таблица b является подмножеством a. c) ОК, не имеет значения, в каком порядке выбираются имена в оригиналах. Граф делает работу :) –  Topera 18.05.2011 в 00:31
  • Вы хорошо пойдете тогда ;-) Я решил, что вы получили ответ, который вам нужен, я в основном хотел указать другим на то, что нужно знать в этом решении. Я думаю, что использование COUNT здесь является гладким. –  DCookie 18.05.2011 в 00:48
  • Это решение не будет работать, если таблица B содержит значения, которые не указаны в таблице A. –  Allan 19.05.2011 в 16:00
  • @Adrian: они будут включены, но их количество будет равно 1, поэтому они будут смешаны со значениями из таблицы A. –  Allan 19.05.2011 в 20:09
Показать остальные комментарии
25

Вы хотите сделать это:

select * from 
(
    SELECT id, 2 as ordered FROM a -- returns 1,4,2,3
    UNION
    SELECT id, 1 as ordered FROM b -- returns 2,1
)
order by ordered

Обновление

Я заметил, что даже если у вас есть две разные таблицы, вы присоединяетесь к идентификаторам, то есть, если у вас есть 1 в обеих таблицах, вы получаете только одно вхождение. Если это желаемое поведение, вы должны придерживаться UNION . Если нет, замените на UNION ALL .

Поэтому я также замечаю, что если вы перейдете на код, который я предложил, вы начнете получать как 1 , так и 2 (из a и b ). В этом случае вы можете изменить предлагаемый код на:

select distinct id from 
(
    SELECT id, 2 as ordered FROM a -- returns 1,4,2,3
    UNION
    SELECT id, 1 as ordered FROM b -- returns 2,1
)
order by ordered
    
ответ дан Adrian Carneiro 17.05.2011 в 22:38
  • +1 И вы можете опустить псевдоним столбца во второй части союза –  Andomar 17.05.2011 в 22:39
  • Да, я знаю. Но в SO вы должны быть быстрыми :) –  Adrian Carneiro 17.05.2011 в 22:40
  • Это было быстро и идеально! Спасибо человеку! –  Topera 17.05.2011 в 22:48
  • Ups! Не так идеально: я получаю дублированные результаты ... и отдельные не работают ... –  Topera 17.05.2011 в 22:55
  • В ответе есть обновление, вы должны взглянуть ... –  Adrian Carneiro 17.05.2011 в 23:12
Показать остальные комментарии
2

@ Ответ Адриена не работает. Он дает ORA-01791.

Правильный ответ (для заданного вопроса) должен быть:

select id
from 
 (SELECT id, 2 as ordered FROM a -- returns 1,4,2,3
  UNION ALL
  SELECT id, 1 as ordered FROM b -- returns 2,1
  )
group by id
order by min(ordered)

Пояснение:

  1. «UNION ALL» объединяет 2 набора. «UNION» бесполезен, потому что два набора не могут быть одинаковыми, потому что упорядоченное поле отличается.
  2. «group by» затем удаляет дубликаты
  3. «Порядок по min (упорядочен)» гарантирует, что элементы таблицы b сначала

Это решает все случаи, даже если таблица b содержит больше или разных элементов, а затем таблицу

    
ответ дан rvheddeg 30.01.2017 в 14:06
1

@ Ответ Адриана вполне подходит, я просто хотел поделиться другим способом достижения того же результата:

select nvl(a.id, b.id)
from a full outer join b on a.id = b.id
order by b.id;
    
ответ дан Allan 19.05.2011 в 16:04
0
SELECT id, 1 AS sort_order
  FROM b
UNION
SELECT id, 2 AS sort_order
  FROM a
MINUS
SELECT id, 2 AS sort_order
  FROM b
ORDER BY 2;
    
ответ дан onedaywhen 18.05.2011 в 12:08