mysql에서 union 및 order by 절 사용


123

mysql 쿼리에서 union과 함께 order by를 사용하고 싶습니다. 내 사이트에서 검색 할 거리에 따라 테이블에서 다른 기준에 따라 다른 유형의 레코드를 가져오고 있습니다. 첫 번째 선택 쿼리는 정확한 장소 검색과 관련된 데이터를 반환합니다. 두 번째 선택 쿼리는 검색된 장소에서 5km 이내의 거리와 관련된 데이터를 반환합니다. 세 번째 선택 쿼리는 검색된 장소에서 5-15km 이내의 거리와 관련된 데이터를 반환합니다.

그런 다음 Union을 사용하여 모든 결과를 병합하고 페이지에 페이지를 표시합니다. 적절한 제목 아래 '정확한 검색 결과' , '5 kms 이내 결과'

이제 id 또는 add_date를 기준으로 결과를 정렬하고 싶습니다. 하지만 내 쿼리의 끝에 order by 절을 추가하면 (query1 union query 2 union query 3 order by add_date). 모든 결과를 정렬합니다. 그러나 내가 원하는 것은 각 제목 아래에 정렬되어야한다는 것입니다.


각 테이블에서 정렬하려는 필드의 유형은 무엇입니까?
user151841 2010-08-20

답변:


221

다른 기준으로 정렬하기 전에 먼저 정렬 할 수있는 각 선택 항목에 rank라는 가상 열을 추가하여이를 수행 할 수 있습니다. 예 :

select *
from (
    select 1 as Rank, id, add_date from Table 
    union all
    select 2 as Rank, id, add_date from Table where distance < 5
    union all
    select 3 as Rank, id, add_date from Table where distance between 5 and 15
) a
order by rank, id, add_date desc

9
왜 있고 a끝이 있습니까?
Uday Hiwarale

25
MySQL에서는 파생 테이블에 별칭이 있어야합니다.
RedFilter

4
@RedFilter, 나는 그것을 얻지 못합니다. 3 개의 테이블을 모두 선택하고 다음을 수행 할 수 있을 때 "모두 파생 테이블로 선택"의 요점은 무엇입니까 order by? ( "전체 UNION결과 를 정렬하거나 제한하려면 개별 SELECT문을 괄호로 묶고 마지막 문 뒤에 ORDER BY또는 LIMIT뒤에 배치 " ). 코드를 i.stack.imgur.com/LpTMU.png
Pacerier

1
@Pacerier 해당 구문이 MySQL과 함께 작동한다면 시도해보십시오! 내 구문은 조금 더 교차 플랫폼이며 일반적으로 MySQL을 사용하지 않습니다. 나는 실제로 더 일반적인 경우에서 작동하기 때문에 그것을 선호합니다. 예를 들어, 마지막 UNION 쿼리에서 처음 10 개의 일치 만 원하는 경우를 고려하십시오. 어쨌든 내 구문으로 돌아 가야한다고 생각합니다.
RedFilter

1
@Pacerier, 또한 이러한 방식의 값을 사용하면 상위 "select *"가 대신 "select id, add_date"가 될 수 있으며보고 싶지 않은 경우 결과에서 "rank"를 제거 할 수 있습니다.
Dev Null

45

이를 위해 하위 쿼리를 사용할 수 있습니다.

select * from (select values1 from table1 order by orderby1) as a
union all
select * from (select values2 from table2 order by orderby2) as b

1
Tnx, 주문을 분리하는 것이 좋습니다. 또한 주문 조항이 공통적 인 경우 다른 배열을 가질 수 있지만 결과를 분리하고 싶습니다 (주문을 분리하는 대신) : SELECT * FROM ( SELECT aaa AS Col, 1 AS Official FROM table1 UNION ALL SELECT bbb AS Col, 0 AS Official FROM table2 ) AS tbl ORDER BY Official, Col
Alix

18
이다 잘못된 : 사용 ORDER BY개인에 대한 SELECT문은 행이 최종 결과에 표시되는 순서에 대해 아무것도 의미하지 않습니다
shmosel

당신이 옳습니다. 받아 들여지는 대답도 올바른 것입니다. 이것은 내가 그것을 테스트했을 때 잘 작동했습니다.
rickythefox

shmosel (및 rickythefox)-union all은 중복을 제거하지 않으므로 개별 정렬 선택의 종류를 변경할 이유가 없습니다. 이것이 과거에 당신을 위해 일한 이유이며 미래에 당신을 위해 일할 이유입니다. 최종 결과에서 엉망이되는 순서는 행을 효율적으로 결합하기 위해 일종의 정렬이 필요한 UNION (DISTINCT) 때문입니다. 또는보다 구체적으로 행을 효율적으로 결합하기 때문에 정렬합니다. 따라서 하위 쿼리를 보존하기 위해 모두 공용체에 의존 할 수 있습니다.
Gerard ONeill

2
이것은 이전 MySQL 버전에서 훌륭하게 작동했지만 이제는이 접근 방식이 작동 하지 않습니다 . SQL 표준은 하위 쿼리의 순서를 유지하는 것을 보장하지 않기 때문입니다.
Andrei

28
(select add_date,col2 from table_name) 
  union 
(select add_date,col2 from table_name) 
  union 
(select add_date,col2 from table_name) 

order by add_date

이것은 효과가 있었지만 이상하게도 한 가지를 변경해야했습니다. 주문한 필드에 공유 별칭을 제공해야했습니다. 그 외에도 일했습니다, 감사합니다!
HoldOffHunger

9

통합 쿼리에는 하나의 마스터 ORDER BY절인 IIRC 만있을 수 있습니다 . 이를 얻으려면 더 큰를 구성하는 각 쿼리에 UNION쿼리의 위해에 의해 정렬 하나 개의 필드 당신이 될 것입니다 필드를 추가 UNIONORDER BY.

예를 들어, 다음과 같은 것이있을 수 있습니다.

SELECT field1, field2, '1' AS union_sort
UNION SELECT field1, field2, '2' AS union_sort
UNION SELECT field1, field2, '3' AS union_sort
ORDER BY union_sort

해당 union_sort필드는 정렬 기준이 될 수 있습니다. 이 예에서는 첫 번째 테이블의 결과를 먼저, 두 번째 테이블의 결과를 두 번째 등으로 입력합니다.


9

모두 통합은 정렬이나 병합없이 레코드 세트에 레코드를 추가하는 방법입니다 (union과 반대 임).

예를 들면 :

select * from (
    select col1, col2
    from table a
    <....>
    order by col3
    limit by 200
) a
union all
select * from (
    select cola, colb
    from table b
    <....>
    order by colb
    limit by 300
) b

개별 쿼리를 더 명확하게 유지하고 각 쿼리에서 다른 매개 변수로 정렬 할 수 있습니다. 그러나 선택한 답변의 방식을 사용하면 정렬을 개념화하고 있기 때문에 복잡성과 데이터의 관련성에 따라 더 명확해질 수 있습니다. 또한 쿼리 프로그램에 인공 열을 반환하여 정렬하거나 구성 할 수있는 컨텍스트를 가질 수도 있습니다.

그러나이 방법은 추가 변수를 도입하지 않고, 정렬을 포함하여 각 쿼리를 쉽게 분리 할 수 ​​있다는 장점이 있습니다. 제한을 추가하는 기능은 단순히 추가 보너스입니다.

물론 공용체를 모두 공용체로 바꾸고 전체 쿼리에 대한 정렬을 추가 할 수 있습니다. 또는 인공 ID를 추가합니다.이 경우 각 쿼리에서 다른 매개 변수로 쉽게 정렬 할 수 있지만 그렇지 않으면 허용 된 답변과 동일합니다.


4

조인 플러스 조합에서이 작업을 수행했습니다.

(SELECT 
   table1.column1,
   table1.column2,
   foo1.column4
 FROM table1, table2, foo1, table5
 WHERE table5.somerecord = table1.column1
 ORDER BY table1.column1 ASC, table1.column2 DESC
)

UNION

(SELECT
    ... Another complex query as above
)

ORDER BY column1 DESC, column2 ASC

3

mysql ORDER BY과 함께 사용되는 하위 쿼리 내 에서 절 을 사용하면 절이 UNION최적화됩니다 ORDER BY.

기본적으로 a UNION는 순서가 지정되지 않은 목록을 반환하므로 an ORDER BY은 아무 작업도 수행하지 않기 때문입니다.

최적화는 문서에 언급 되어 있으며 다음 과 같이 말합니다.

ORDER BY 또는 LIMIT를 개별 SELECT에 적용하려면 SELECT를 묶는 괄호 안에 절을 넣으십시오.

(SELECT a FROM t1 WHERE a=10 AND B=1 ORDER BY a LIMIT 10) UNION
(SELECT a FROM t2 WHERE a=11 AND B=2 ORDER BY a LIMIT 10);

그러나 개별 SELECT 문에 ORDER BY를 사용하는 것은 UNION이 기본적으로 정렬되지 않은 행 집합을 생성하기 때문에 최종 결과에 행이 나타나는 순서에 대해 아무런 의미가 없습니다. 따라서이 컨텍스트에서 ORDER BY를 사용하는 것은 일반적으로 LIMIT와 함께 사용되므로 SELECT에 대해 검색 할 선택된 행의 하위 집합을 결정하는 데 사용됩니다. 최종 UNION 결과. SELECT에서 LIMIT없이 ORDER BY가 표시되면 어쨌든 효과가 없기 때문에 최적화됩니다.

이것의 마지막 문장은 효과가 있어야하기 때문에 약간 오해의 소지가 있습니다. 이 최적화는 서브 쿼리 내에서 주문해야하는 상황에있을 때 문제를 일으 킵니다.

MySQL이이 최적화를 수행하지 않도록 강제하려면 다음과 같이 LIMIT 절을 추가 할 수 있습니다.

(SELECT 1 AS rank, id, add_date FROM my_table WHERE distance < 5 ORDER BY add_date LIMIT 9999999999)
UNION ALL
(SELECT 2 AS rank, id, add_date FROM my_table WHERE distance BETWEEN 5 AND 15 ORDER BY rank LIMIT 9999999999)
UNION ALL
(SELECT 3 AS rank, id, add_date from my_table WHERE distance BETWEEN 5 and 15 ORDER BY id LIMIT 9999999999)

높음 LIMITOFFSET페이지 매김과 같은 작업을 수행하려는 경우 전체 쿼리에을 추가 할 수 있음을 의미합니다 .

이는 또한 ORDER BY각 유니온에 대해 서로 다른 열을 사용할 수 있다는 추가 이점을 제공합니다 .


0

시험:

SELECT result.* 
FROM (
 [QUERY 1]
 UNION
 [QUERY 2]
) result
ORDER BY result.id

여기서 [QUERY 1] 및 [QUERY 2]는 병합하려는 두 개의 쿼리입니다.


0

이는 전체 결과 집합을 정렬하기 때문입니다. 통합의 모든 부분을 개별적으로 정렬해야하거나 ORDER BY (어떤 것 즉, 하위 쿼리 거리) THEN (어떤 것, 즉 행 ID) 절을 사용할 수 있습니다.


0

나는 다음과 같이 결합하기 전에 각 쿼리에 순서를 추가하려고했습니다.

(select * from table where distance=0 order by add_date) 
union 
(select * from table where distance>0 and distance<=5 order by add_date)

그러나 그것은 작동하지 않는 것 같습니다. 실제로 각 선택의 행 내에서 순서를 지정하지 않았습니다.

나는 당신이 order by를 외부에 유지하고 where 절의 열을 order by에 추가해야한다고 생각합니다.

(select * from table where distance=0) 
union 
(select * from table where distance>0 and distance<=5) 
order by distance, add_date

범위별로 그룹화하고 싶기 때문에 약간 까다로울 수 있지만 가능해야한다고 생각합니다.


user151841 아래의 union_sort 아이디어는 그룹화를 처리하는 좋은 방법이 될 것입니다
Mike C
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.