web-dev-qa-db-ja.com

MySQLクエリGROUP BY日/月/年

年、月、日など、決まった期間内に何個のレコードがあり、TIMESTAMPフィールドがあるかを数えるために単純なクエリを作成することは可能ですか。

SELECT COUNT(id)
FROM stats
WHERE record_date.YEAR = 2009
GROUP BY record_date.YEAR

あるいは:

SELECT COUNT(id)
FROM stats
GROUP BY record_date.YEAR, record_date.MONTH

毎月の統計を持っています。

ありがとうございます。

573
GROUP BY YEAR(record_date), MONTH(record_date)

MySQLの 日付と時刻の関数 をチェックしてください。

912
codelogic
GROUP BY DATE_FORMAT(record_date, '%Y%m')

(主に、潜在的な格下げ者への)。現在、これは他の提案ほど効率的ではないかもしれません。それでも、私はそれを代替手段として残し、他の解決策がどれほど速いかを見るのに役立つことができるものも残します。また、時間が経つにつれて、最適化に関してMySQLのエンジンに変更が加えられることもあります。将来的には、他のほとんどのものと効率がかなり匹敵するようになります。

201
Andriy M

私は上記の「WHERE」文を使ってみましたが、誰も修正していなかったので正しいと思いましたが、私は間違っていました。いくつかの検索の後、私はこれがWHEREステートメントの正しい式であることを発見したので、コードは次のようになります。

SELECT COUNT(id)  
FROM stats  
WHERE YEAR(record_date) = 2009  
GROUP BY MONTH(record_date)
39
dimazaid

これを試してください

SELECT COUNT(id)
FROM stats
GROUP BY EXTRACT(YEAR_MONTH FROM record_date)

EXTRACT(unit FROM date) 関数は、使用されるグループ化が少なくなり、関数が数値を返すのでよくなります。

グループ化時の比較条件は、DATE_FORMAT関数(文字列値を返す)よりも高速になります。 SQL比較条件(WHERE、HAVING、ORDER BY、GROUP BY)にストリング以外の値を返すfunctionフィールドを使用してみてください。

37
fu-chi

あなたの検索が数年を超えていて、それでも毎月グループ化したいのであれば、私はお勧めします:

バージョン#1:

SELECT SQL_NO_CACHE YEAR(record_date), MONTH(record_date), COUNT(*)
FROM stats
GROUP BY DATE_FORMAT(record_date, '%Y%m')

バージョン#2 (より効率的)

SELECT SQL_NO_CACHE YEAR(record_date), MONTH(record_date), COUNT(*)
FROM stats
GROUP BY YEAR(record_date)*100 + MONTH(record_date)

これらのバージョンを1,357,918行( innodb )の大きなテーブルで比較したところ、2番目のバージョンのほうが良い結果が得られました。

バージョン1 平均10回の実行):1.404秒
version2 (平均10回の実行):0.780秒

(MySQLがクエリにキャッシュするのを防ぐためにSQL_NO_CACHEキーが追加されました。)

25
mr.baby123

MySQLで日付別にグループ化したい場合は、以下のコードを使用してください。

 SELECT COUNT(id)
 FROM stats
 GROUP BY DAYOFMONTH(record_date)

これがこのスレッドを見つけようとしている人たちにとって時間を節約することを願っています。

16
Haijerome

特定の年(たとえば2000年)のレコードをフィルタしたい場合は、WHERE句を次のように最適化します。

SELECT MONTH(date_column), COUNT(*)
FROM date_table
WHERE date_column >= '2000-01-01' AND date_column < '2001-01-01'
GROUP BY MONTH(date_column)
-- average 0.016 sec.

の代わりに:

WHERE YEAR(date_column) = 2000
-- average 0.132 sec.

結果は、300k行とindex on date列を含むテーブルに対して生成されました。

GROUP BY節に関しては、上記の表に対して3つのバリアントをテストしました。結果は次のとおりです。

SELECT YEAR(date_column), MONTH(date_column), COUNT(*)
FROM date_table
GROUP BY YEAR(date_column), MONTH(date_column)
-- codelogic
-- average 0.250 sec.

SELECT YEAR(date_column), MONTH(date_column), COUNT(*)
FROM date_table
GROUP BY DATE_FORMAT(date_column, '%Y%m')
-- Andriy M
-- average 0.468 sec.

SELECT YEAR(date_column), MONTH(date_column), COUNT(*)
FROM date_table
GROUP BY EXTRACT(YEAR_MONTH FROM date_column)
-- fu-chi
-- average 0.203 sec.

最後の人が勝者です。

11
Salman A

現在有効な、同様に機能するが、より短くより柔軟な代替品を備えた完全で単純な解決策:

SELECT COUNT(*) FROM stats
-- GROUP BY YEAR(record_date), MONTH(record_date), DAYOFMONTH(record_date)
GROUP BY DATE_FORMAT(record_date, '%Y-%m-%d')
9
Cees Timmerman

最新の月ごとに並べられた各年の月ごとの行数を含む月ごとの統計を取得したい場合は、以下を試してください。

SELECT count(id),
      YEAR(record_date),
      MONTH(record_date) 
FROM `table` 
GROUP BY YEAR(record_date),
        MONTH(record_date) 
ORDER BY YEAR(record_date) DESC,
        MONTH(record_date) DESC
7
user3019799

GROUP BYでMysql DATE_FORMAT() functionを実行するだけです。レコードが数年にまたがって同じ月が異なる年になるような場合には、わかりやすくするために追加の列を追加することをお勧めします。これをカスタマイズできるオプションはたくさんあります。始める前にこれを読んでください。それはあなたにとって非常に役立つはずです。これはあなたの理解のためのサンプルクエリです。

SELECT
    COUNT(id),
    DATE_FORMAT(record_date, '%Y-%m-%d') AS DAY,
    DATE_FORMAT(record_date, '%Y-%m') AS MONTH,
    DATE_FORMAT(record_date, '%Y') AS YEAR,

FROM
    stats
WHERE
    YEAR = 2009
GROUP BY
    DATE_FORMAT(record_date, '%Y-%m-%d ');
6
Faisal

次の問合せは、Oracle Database 12c Release 12.1.0.1.0で機能しました。

SELECT COUNT(*)
FROM stats
GROUP BY 
extract(MONTH FROM TIMESTAMP),
extract(MONTH FROM TIMESTAMP),
extract(YEAR  FROM TIMESTAMP);
5
Minisha

次のように、1年間のグループ選択を最適化することを好みます。

SELECT COUNT(*)
  FROM stats
 WHERE record_date >= :year 
   AND record_date <  :year + INTERVAL 1 YEAR;

このようにして、年を一度にバインドすることができます。 '2009'、名前付きパラメーターを使用し、'-01-01'を追加したり、'2010'を個別に渡すことを心配する必要はありません。

また、おそらく行をカウントしているだけで、idNULLになることはないので、COUNT(*)よりCOUNT(id)の方が好きです。

2
Arth

.... group by to_char(date, 'YYYY') - > 1989

.... group by to_char(date,'MM') - > 05

.... group by to_char(date,'DD') ---> 23

.... group by to_char(date,'MON') ---> 5月

.... group by to_char(date,'YY') ---> 89

0
aromita sen