web-dev-qa-db-ja.com

mysqlのGROUP BY名の前の日付と時刻による並べ替え

私はこのようなテーブルを持っています:

name    date         time
tom | 2011-07-04 | 01:09:52
tom | 2011-07-04 | 01:09:52
mad | 2011-07-04 | 02:10:53
mad | 2009-06-03 | 00:01:01

最も古い名前が最初に欲しい:

SELECT * 
ORDER BY date ASC, time ASC 
GROUP BY name

(->機能しません!)

今、それは私に最初の狂気(より早い日付を持っている)、そしてトムを与えるべきです

しかし、GROUP BY name ORDER BY date ASC, time ASCは、並べ替える前にグループ化されるため、最初に新しい気違いを与えます!

繰り返しますが、問題は、GROUP BYはORDER BYの前にある必要があるため、iグループの前に日付と時刻でソートできないことです!

51
CodingYourLife

別の方法:

SELECT * 
FROM (
    SELECT * 
    ORDER BY date ASC, time ASC 
) AS sub
GROUP BY name

GROUP BYは、最初に一致した結果でグループ化します。最初に一致したヒットが必要なものである場合、すべてが期待どおりに動作するはずです。

副照会が他の条件を使用するよりも理にかなっているため、この方法の方が好きです。

71
swbeeton

私はこれがあなたが探しているものだと思います:

SELECT name, min(date)
FROM myTable
GROUP BY name
ORDER BY min(date)

とりあえず、STR_TO_DATE経由でmysql日付を作成する必要があります。

STR_TO_DATE(date + ' ' + time, '%Y-%m-%d %h:%i:%s')

そう :

SELECT name, min(STR_TO_DATE(date + ' ' + time, '%Y-%m-%d %h:%i:%s'))
FROM myTable
GROUP BY name
ORDER BY min(STR_TO_DATE(date + ' ' + time, '%Y-%m-%d %h:%i:%s'))
26
Cyril Gandon

User1908688の回答にコメントすることは許可されていないため、MariaDBユーザーへのヒントを以下に示します。

SELECT *
FROM (
     SELECT *
     ORDER BY date ASC, time ASC
     LIMIT 18446744073709551615
     ) AS sub
GROUP BY sub.name

https://mariadb.com/kb/en/mariadb/why-is-order-by-in-a-from-subquery-ignored/

23
Vincent

これは私のために働いた:

SELECT *
FROM your_table
WHERE id IN (
    SELECT MAX(id)
    FROM your_table
    GROUP BY name
);
9
jokermt235

副選択を使用します。

select name, date, time
from mytable main
where date + time = (select min(date + time) from mytable where name = main.mytable)
order by date + time;
3
Bohemian

この質問にはさまざまなバリエーションがあり、単一のDATETIMEフィールドのみがあり、group byまたはlimitの後にdistinctが必要でした。 datetimeフィールド、しかしこれは私を助けたものです:

select distinct (column) from
(select column from database.table
order by date_column DESC) as hist limit 10

分割フィールドを使用したこの例では、連結で並べ替えることができれば、次のようなもので逃げることができます。

select name,date,time from
(select name from table order by concat(date,' ',time) ASC)
as sorted

次に、制限したい場合は、制限ステートメントを最後に追加するだけです:

select name,date,time from
(select name from table order by concat(date,' ',time) ASC)
as sorted limit 10
0
AbsoluteƵERØ

これを解決する別の方法は、LEFT JOINを使用することです。これはより効率的です。おそらく、日付と時刻を1つのdatetime列に格納するのが一般的であるため、日付フィールドのみを考慮する例から始めます。また、わかりやすくするためにクエリを単純に保ちたいと思います。

したがって、この特定の例では、date列に基づいてoldestレコードを表示し、テーブルを仮定すると名前はpeopleと呼ばれ、次のクエリを使用できます。

SELECT p.* FROM people p
LEFT JOIN people p2 ON p.name = p2.name AND p.date > p2.date
WHERE p2.date is NULL
GROUP BY p.name

LEFT JOINが行うことは、p.date列が最小値の場合、左結合の値が小さいp2.dateがなくなるため、対応するp2.dateNULLになります。したがって、WHERE p2.date is NULLを追加することで、最も古い日付のレコードのみを表示するようにします。

同様に、代わりにnewestレコードを表示する場合は、LEFT JOINの比較演算子を変更するだけです。

SELECT p.* FROM people p
LEFT JOIN people p2 ON p.name = p2.name AND p.date < p2.date
WHERE p2.date is NULL
GROUP BY p.name

さて、date + timeが個別の列であるこの特定の例では、2つの列を組み合わせたdatetimeに基づいてクエリを実行する場合、何らかの方法でそれらを追加する必要があります。次に例を示します。

SELECT p.* FROM people p
LEFT JOIN people p2 ON p.name = p2.name AND p.date + INTERVAL TIME_TO_SEC(p.time) SECOND > p2.date + INTERVAL TIME_TO_SEC(p2.time) SECOND
WHERE p2.date is NULL
GROUP BY p.name

特定の列のグループごとの最大値を保持する行 ページで、これについての詳細を読むことができます(これを達成するためのいくつかの他の方法も参照してください)。

0
Ben