web-dev-qa-db-ja.com

列の値ごとにSELECT LIMIT 1?

次の表があるとしましょう

-----------------------------
| user_id   | comment       |
-----------------------------
| 2         | thats cool    |
| 2         | awesome       |
| 3         | i hate this   |
| 3         | okay          |
| 6         | this is weird |
| 6         | hello?        |
| 6         | what is it    |
| 9         | how are you   |
| 16        | too slow      |
| 16        | yes           |
| 17        | alrighty      |
-----------------------------

user_idごとに1行を選択するにはどうすればよいですか?だから私の結果は:

-----------------------------
| user_id   | comment       |
-----------------------------
| 2         | thats cool    |
| 3         | i hate this   |
| 6         | this is weird |
| 9         | how are you   |
| 16        | too slow      |
| 17        | alrighty      |
-----------------------------

これは単一の効率的なクエリで可能ですか?またはサブ選択が必要ですか?単一の列でDISTINCTをどういうわけか使用できますか?

10
Jake Wilson

それがGROUP BYの用途です。 (グループごとに)1行を取得します。この場合、すべての個別のuser_id値が表示され、残りの列については、MIN()MAX()AVG()SUM()グループごとに複数の値があり、表示できるのは1つだけなので。

SELECT
    user_id
  , MIN(comment) AS comment  -- it will show the first in alphabetical order  
                             -- you could also use MAX()
FROM
    tableX
GROUP BY
    user_id ;

MySQLは、ユーザーごとに1つの(多かれ少なかれランダムな)コメントを返す、次の非正統的なソリューションも許可します。

SELECT
    user_id
  , comment
FROM
    tableX
GROUP BY
    user_id ;

この最後のクエリは機能しませんが、(より厳密な)ONLY_FULL_GROUP_BYモードが有効になっている場合はエラーが発生します。最近リリースされた5.7バージョンでは、このモードがデフォルトであり、新しい関数ANY_VALUE()が提供されています。詳細については、 MySQLによるGROUP BYの処理 ページを参照してください。クエリは今書くことができます:

SELECT
    user_id
  , ANY_VALUE(comment) AS comment
FROM
    tableX
GROUP BY
    user_id ;

「非標準」バージョンまたは最近のANY_VALUE()関数を使用して、SELECTリストに列を追加した場合、それらの値が同じ行からのものであるとは限らないことに注意してください。同じグループの行。それらが選択される方法は完全にランダムではなく、実行プランと使用されるインデックスによって異なります。

9
ypercubeᵀᴹ