質問と呼ばれる次の表があります。
ID | asker
1 | Bob
2 | Bob
3 | Marley
各質問者を1回だけ選択し、同じ名前の質問者が複数いる場合は、最も高いIDの質問者を選択します。したがって、期待される結果:
ID | asker
3 | Marley
2 | Bob
次のクエリを使用します。
SELECT * FROM questions GROUP by questions.asker ORDER by questions.id DESC
次の結果が得られます。
ID | asker
3 | Marley
1 | Bob
したがって、最後のものではなく、最初に遭遇した「ボブ」を選択します。
ありがとう
id
ごとに最後のasker
が必要な場合は、集約関数を使用する必要があります。
SELECT max(id) as id,
asker
FROM questions
GROUP by asker
ORDER by id DESC
異常な結果が得られた理由は、MySQLがGROUP BY
の拡張機能を使用して、選択リスト内のアイテムを非集計にし、GROUP BY句に含めないようにするためです。ただし、MySQLは返される値を選択できるため、これにより予期しない結果が生じる可能性があります。 ( GROUP BYのMySQL拡張機能 を参照)
MySQL Docsから:
MySQLは、GROUP BY句で指定されていない非集計列を選択リストが参照できるように、GROUP BYの使用を拡張します。 ...この機能を使用して、不必要な列のソートとグループ化を回避することにより、パフォーマンスを向上させることができます。ただし、これは主に、GROUP BYで指定されていない各非集計列のすべての値が各グループで同じ場合に役立ちます。サーバーは各グループから任意の値を自由に選択できるため、それらが同じでない限り、選択される値は不定です。さらに、各グループからの値の選択は、ORDER BY句を追加しても影響を受けません。結果セットのソートは値が選択された後に行われ、ORDER BYはサーバーが選択する値に影響しません。
テーブルから返す必要がある他の列があり、取得できる一貫性のない結果のためにGROUP BY
に追加したくない場合は、サブクエリを使用して返すことができます。 ( デモ )
select
q.Id,
q.asker,
q.other -- add other columns here
from questions q
inner join
(
-- get your values from the group by
SELECT max(id) as id,
asker
FROM questions
GROUP by asker
) m
on q.id = m.id
order by q.id desc
通常、MySQLは昇順のレコードのみでグループを許可します。したがって、グループ化する前にレコードを注文できます。
SELECT * FROM( SELECT * FROM質問 ORDER BY id DESC )AS質問 GROUP BY question.asker
すべてのasker
の最大IDを取得するには、_GROUP BY
_およびMAX()
を使用してレコードをグループ化する必要があります。
_SELECT asker, MAX(ID) ID
FROM TableName
GROUP BY asker
_
出力
_╔════════╦════╗
║ ASKER ║ ID ║
╠════════╬════╣
║ Bob ║ 2 ║
║ Marley ║ 3 ║
╚════════╩════╝
_
他のユーザーは、MAX(ID)を使用して必要な結果を取得することについて正しいです。クエリが機能しない理由がわからない場合は、ORDER BY
が発生します後GROUP BY
。
この回答を書いているのは、受け入れられた回答の@Tarynの最初/より短い代替案が、GROUP BYおよびMAXで使用される列だけを正確に選択している場合にのみ機能するためです。ユーザーが質問するのは、テーブル内のすべての列を選択することです(彼はSELECT *を使用しました)。そのため、テーブルに別の3番目の列を追加すると、クエリ結果のその列の値が正しくなくなります。異なるテーブル行から混合値を取得します。 @Tarynの2番目/より長い選択肢(内部結合とサブクエリを使用)は機能しますが、クエリは無駄に複雑で、は私の単純な選択肢よりも5倍遅いです以下。
テーブルquestions
を考慮してください:
_id | asker
-----------
1 | Bob
2 | Bob
3 | Marley
_
クエリSELECT max(id) as id, asker FROM questions GROUP BY asker ORDER BY id DESC
は、expectedを返します。
_id | asker
-----------
3 | Marley
2 | Bob
_
次に、別のテーブルquestions
を考えます。
_id | asker | other
-------------------
1 | Bob | 1st
2 | Bob | 2nd
3 | Marley | 3rd
_
クエリSELECT max(id) as id, asker, other FROM questions GROUP BY asker ORDER BY id DESC
は以下を返しますunexpected:
_id | asker | other
-------------------
3 | Marley | 3rd
2 | Bob | 1st
_
...結果の2行目のother
の値は、_id=2
_は表の2行目から来るが、_other=1st
_は表の1行目から来るため、正しくないことに注意してください。これが、タリンの回答レポートの多くのユーザーが、このソリューションが機能しないと報告している方法です。
別の列も選択する場合の簡単な解決策は、_GROUP BY
_ + DESC
を使用することです。
_SELECT id, asker, other FROM questions GROUP BY asker DESC
_
_id | asker | other
-------------------
3 | Marley | 3rd
2 | Bob | 2nd
_
(デモを参照: https://www.db-fiddle.com/f/esww483qFQXbXzJmkHZ8VT/1 )
...しかし、この単純なソリューションにはいくつかの制限があります。
asker
(この場合インデックスが適切であるため、パフォーマンスが向上するため問題ありません。GROUPBYは通常作成が必要ですtmpテーブルのが、インデックスが利用可能な場合、tmpテーブルは作成されないため、高速です)SET SESSION sql_mode = '';
_)を無効にするか、集約されていない選択列でANY_VALUE()
を使用する必要があります。GROUP BY col1 ORDER BY col1 ASC/DESC
_があります:_SELECT id, asker, other FROM questions GROUP BY asker ORDER BY asker DESC
_
_id | asker | other
-------------------
3 | Marley | 3rd
2 | Bob | 2nd
_
(デモを参照: https://www.db-fiddle.com/f/esww483qFQXbXzJmkHZ8VT/11 )
...結果は_GROUP BY ... DESC
_の場合と同じです(InnoDBを使用してインデックスを作成することを忘れないでください)。
その理由は ORDER BY
が実行されます[〜#〜] after [〜#〜]GROUP BY
。
これを試して:
SELECT * FROM questions
WHERE id IN
(
SELECT max(id) as id
FROM questions
GROUP by asker
ORDER by id DESC
)
すべての列を取得するには:
SELECT * FROM questions
WHERE id IN
(SELECT max(id) as id, asker
FROM questions
GROUP by asker
ORDER by id DESC)
@bluefeetの回答の改善されたバージョン。