web-dev-qa-db-ja.com

1つの列の値が異なる最新の3つのレコードを選択します

次の表があります。

    id       time      text      otheridentifier
    -------------------------------------------
    1        6         Apple     4
    2        7         orange    4
    3        8         banana    3
    4        9         pear      3
    5        10        grape     2

私がやりたいのは、otheridentifiersが異なる3つの最新のレコード(時間順)を選択することです。したがって、この場合、結果はid 's:5、4、および2になります。

id =同じotheridentifierフィールドを持つ最新のレコードがあるため、3はスキップされます。

これが私がやろうとしたことです:

SELECT * FROM `table` GROUP BY (`otheridentifier`) ORDER BY `time` DESC LIMIT 3

しかし、期待どおり、5、4、2ではなく、id = 5、、および1の行を取得することになります。

誰かがこのクエリがなぜ私が期待したものを返さないのか教えてもらえますか? ORDER BYをASCに変更してみましたが、これは返された行を1、3、5に再配置するだけです。

45
atp

SQLステートメント内の句の位置に反映されるように、グループ化は順序付けの前に行われるため、期待どおりの結果は返されません。残念ながら、必要な行を取得するには、より洗練されたものにする必要があります。これを試して:

SELECT *
FROM `table`
WHERE `id` = (
    SELECT `id`
    FROM `table` as `alt`
    WHERE `alt`.`otheridentifier` = `table`.`otheridentifier`
    ORDER BY `time` DESC
    LIMIT 1
)
ORDER BY `time` DESC
LIMIT 3
34
chaos

テーブル自体を結合してotheridentifierごとに最後のエントリをフィルタリングし、その上位3行を取得できます。

SELECT last.*
FROM `table` last
LEFT JOIN `table` prev 
    ON prev.`otheridentifier` = last.`otheridentifier`
    AND prev.`time` < last.`time`
WHERE prev.`id` is null
ORDER BY last.`time` DESC 
LIMIT 3
18
Andomar

同様の要件がありましたが、より高度な選択基準がありました。他のいくつかの回答を使用すると、必要なものを正確に取得できませんでしたが、次のようにGROUP BYとORDER BYを実行できることがわかりました。

SELECT t.* FROM (SELECT * FROM table ORDER BY time DESC) t 
GROUP BY t.otheridentifier
4
11101101b
SELECT * FROM table t1 
WHERE t1.time = 
    (SELECT MAX(time) FROM table t2 
     WHERE t2.otheridentifier = t1.otheridentifier)
2
Rytmis

Andomarの回答 は、サブクエリを使用しないという点でおそらく最良です。

別のアプローチ:

select *
from   `table` t1
where  t1.`time` in (
                    select   max(s2.`time`)
                    from     `table` t2
                    group by t2.otheridentifier
                    )

このクエリを使用して正しい答えを得ることができます:

SELECT * FROM 
      (SELECT * FROM `table` order by time DESC)
          t group by otheridentifier
2
php

どうですか

SELECT *, max(time) FROM `table`  group by otheridentifier
1
mbo

これもまた:

SELECT * FROM
OrigTable T INNER JOIN 
( 
SELECT otheridentifier,max(time) AS duration
FROM T
GROUP BY otheridentifier) S
ON S.duration = T.time AND S.otheridentifier = T.otheridentifier.
0
user2450223