Sql Union All * с * "отличным"

UNION объединяет два результата и удаляет дубликаты, а UNION ALL не удаляет дубликаты. UNION также сортирует окончательный результат.

Что я хочу, так это СОЮЗ ВСЕХ без дубликатов и без сортировки. Это возможно?

Причина этого заключается в том, что я хочу, чтобы результат первого запроса был сверху окончательного результата, а второй запрос - внизу. (И каждый отсортирован так, как будто они бегут индивидуально)

8 ответов

Решение

Я заметил, что этот вопрос получил довольно много просмотров, поэтому сначала я отвечу на вопрос, который вы не задавали!

По поводу названия. Чтобы добиться "Sql Union All с " отличным "", просто замените UNION ALL с UNION, Это приводит к удалению дубликатов.

Для вашего конкретного вопроса, учитывая пояснение "Первый запрос должен иметь" приоритет ", поэтому дубликаты должны быть удалены снизу", вы можете использовать

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 также сортирует окончательный результат" - только как артефакт реализации. Это ни в коем случае не гарантирует выполнение сортировки, и если вам нужен определенный порядок сортировки, вы должны указать его с помощью ORDER BY пункт. В противном случае порядок вывода является наиболее удобным для сервера.

Таким образом, ваш запрос на функцию, которая выполняет UNION ALL но удалить дубликаты легко - это называется UNION,


Судя по вашим разъяснениям, вы также считаете, что UNION ALL вернет все результаты первого запроса до результатов последующих запросов. Это также не гарантируется. Опять же, единственный способ достичь определенного порядка - указать его с помощью ORDER BY пункт.

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;

Но реальный ответ: кроме ORDER BY оговорка, порядок сортировки будет произвольным и не гарантируется.

Рассмотрим эти таблицы (стандартный код 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;

Попробуй это:

  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

Я предполагаю, что ваши таблицы - table1 и table2 соответственно, а ваше решение -;

(select * from table1 MINUS select * from table2)
UNION ALL
(select * from table2 MINUS select * from table1)

Сортировка используется для устранения дубликатов и является неявной для DISTINCT а также UNION запросы (но не UNION ALL) - вы все равно можете указать столбцы, по которым вы хотите упорядочить их, если вам нужно их отсортировать по определенным столбцам.

Например, если вы хотите отсортировать по результирующим наборам, вы можете ввести дополнительный столбец и отсортировать по первому:

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

1,1: select 1 from dual union all select 1 from dual 1: select 1 from dual union select 1 from dual

Вы можете сделать что-то вроде этого.

Select distinct name from  (SELECT r.name FROM outsider_role_mapping orm1 
    union all
SELECT r.name FROM user_role_mapping orm2
) tmp;
Другие вопросы по тегам