Сохранение порядка записей в подзапросе с использованием конструкции «Объединение» - PullRequest
1 голос
/ 26 сентября 2011

Я хочу убедиться, что порядок результата из подзапроса сохранен при использовании Union Different. Пожалуйста, обратите внимание, что для объединения дубликатов при выполнении объединения необходимо использовать «объединение различных».

Например:

select columnA1, columnA2 from tableA order by [columnA3] asc
union distinct
select columnB1, columnB2 from tableB

Когда я запускаю это, я ожидаю, что на первом месте будут записи, упорядоченные из подзапроса (выберите columnA1, columnA2 из tableA сортировка по [columnA3] asc) (как возвращено в порядке по columnA3 asc ) затем следуют от tableB.

Я предполагаю, что не могу добавить еще один фиктивный столбец, потому что это сделает объединение отличным, чтобы оно не работало. Итак, это не сработает:

select column1, column2 from 
 ( select column1, column2, 1 as ORD from tableA order by [columnA3] asc
 union distinct
 select column1, column2, 2 as ORD from tableB 
 ) order by ORD

Ответы [ 2 ]

4 голосов
/ 28 сентября 2011

По сути, MySQL не сохраняет порядок записей из подзапроса, используя конструкцию «Объединение». После небольшого исследования я обнаружил, что это работает, если мы добавляем предложение limit или имеем вложенные запросы. Итак, ниже приведены два подхода:

Подход-1: пункт об использовании лимита

         select columnA1, columnA2 from tableA order by [columnA3] asc Limit 100000000
         union distinct
         select columnB1, columnB2 from tableB

Я проверил это поведение, используя несколько наборов данных, и, похоже, оно работает последовательно. Также есть ссылка на это поведение в документации MySQL (http://dev.mysql.com/doc/refman/5.1/en/union.html): «Использование ORDER BY для отдельных операторов SELECT ничего не говорит о порядке, в котором строки появляются в конечном результате, потому что UNION по умолчанию создает неупорядоченный набор строк. Следовательно, использование ORDER BY в этом контексте обычно связано с LIMIT, так что он используется для определения подмножества выбранных строк, которые нужно извлечь для SELECT, даже если это не обязательно влияет на порядок этих строк в окончательный результат UNION. Если ORDER BY появляется без LIMIT в SELECT, он оптимизируется, потому что он все равно не будет иметь никакого эффекта. ”

Обратите внимание, что нет особой причины при выборе LIMIT в 10000000000, кроме наличия достаточно большого числа, чтобы обеспечить охват всех случаев.

Подход-2: вложенный запрос, подобный приведенному ниже, также работает.

        select column1, column2 from 
        ( select column1, column2 order by [columnA3] asc ) alias1
        union distinct
        ( select column1, column2 from tableB )

Я не смог найти причину для работы вложенного запроса. В Интернете были некоторые ссылки (например, от Фила МакКарли в http://dev.mysql.com/doc/refman/5.0/en/union.html), но нет официальной документации от MySQL.

1 голос
/ 26 сентября 2011
select column1, column2 from 
 ( select column1, column2, 1 as ORD from tableA
 union distinct
 select tableB.column1, tableB.column2, 2 as ORD from tableB 
  LEFT JOIN tableA
      ON tableA.column1 = tableB.column1 AND tableA.column2 = tableB.column2
  WHERE tableA.column1 IS NULL
 ) order by ORD

обратите внимание, что UNION не только удаляет дубликаты между отдельными наборами, но и внутри наборов

В качестве альтернативы:

select column1, column2 from 
 ( select column1, column2, 1 as ORD from tableA
 union distinct
 select column1, column2, 2 as ORD from tableB 
 WHERE (column1, column2) NOT IN (SELECT column1, column2 from tableA)
 ) order by ORD
...