web-dev-qa-db-ja.com

mysqlでunionとorder by句を使用する

Mysqlクエリでunionを使用したorder byを使用します。サイトでの検索の距離に基づいたテーブルから、さまざまな基準に基づいてさまざまな種類のレコードを取得しています。最初の選択クエリは、正確な場所検索に関連するデータを返します。 2番目の選択クエリは、検索された場所から5 km以内の距離に関連するデータを返します。 3番目の選択クエリは、検索された場所から5〜15 km以内の距離に関連するデータを返します。

次に、ユニオンを使用してすべての結果をマージし、ページングでページに表示します。 「正確な検索結果」「5 km以内の結果」などの適切な見出しの下

ここで、idまたはadd_dateに基づいて結果を並べ替えます。しかし、クエリの最後にorder by句を追加すると(query1 union query 2 union query 3 order by add_date)すべての結果をソートします。しかし、私が欲しいのは、各見出しの下にソートすることです。

115
Aditya

これを行うには、各選択に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
207
RedFilter

これを行うには、サブクエリを使用できます。

select * from (select values1 from table1 order by orderby1) as a
union all
select * from (select values2 from table2 order by orderby2) as b
40
rickythefox
(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
25
Mitali

忘れないでください、union allは、(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を追加します。この場合、この方法では各クエリの異なるパラメーターで簡単に並べ替えることができますが、それ以外は受け入れられた回答と同じです。

8
Gerard ONeill

ユニオンクエリに含めることができるマスターORDER BY句は、IIRCです。これを取得するには、大きいUNIONクエリを構成する各クエリで、UNIONORDER BYでソートする1​​つのフィールドになるフィールドを追加します。

たとえば、次のようなものがあります

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フィールドには、並べ替えに使用できるものなら何でも指定できます。この例では、最初のテーブルの結果を最初に、2番目のテーブルの結果を2番目などに配置するだけです。

8
user151841

私はこれを結合と結合に取り組んでもらいました。

(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
4
Robert Saylor

試してください:

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

[クエリ1]と[クエリ2]は、マージする2つのクエリです。

0
André Hoffmann

これは、結果セット全体をソートしているため、ユニオンのすべての部分を個別にソートするか、ORDER BY(何かつまりサブクエリ距離)THEN(何かつまり行ID)句を使用できるためです

0
canni

私は次のように結合する前に各クエリに順序を追加しようとしました

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

しかし、うまくいかないようでした。実際には、各選択からの行内の順序付けは行いませんでした。

私はあなたが外側で順序を維持し、where句の列をorder byに追加する必要があると思う

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

範囲ごとにグループ化したいので、これは少し難しいかもしれませんが、実行できるはずです。

0
Mike C

UNIONとともに使用されるサブクエリ内でORDER BY句を使用すると、mysqlはORDER BY句を最適化します。

これは、デフォルトでUNIONが順序付けられていないリストを返すため、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)

LIMITが高いということは、ページネーションなどを実行する場合、クエリ全体にOFFSETを追加できることを意味します。

これにより、ユニオンごとに異なる列をORDER BYできるという追加の利点も得られます。

0
hdifen