web-dev-qa-db-ja.com

MySQLで週ごとにグループ化する方法は?

Oracleのテーブルサーバーは、組み込み関数TRUNC(timestamp,'DY')を提供します。この関数は、任意のタイムスタンプを前の日曜日の午前0時に変換します。 MySQLでこれを行う最良の方法は何ですか?

Oracleでは、TRUNC(timestamp,'MM')を提供して、タイムスタンプが発生する月の最初の日の午前0時にタイムスタンプを変換します。 MySQLでは、これは簡単です。

_TIMESTAMP(DATE_FORMAT(timestamp, '%Y-%m-01'))
_

しかし、この_DATE_FORMAT_トリックは数週間は機能しません。私はWEEK(timestamp)関数を知っていますが、実際には年内の週番号は必要ありません。これは複数年にわたる作業用です。

75
O. Jones

それを考え出した...それは少し面倒ですが、ここにあります。

FROM_DAYS(TO_DAYS(TIMESTAMP) -MOD(TO_DAYS(TIMESTAMP) -1, 7))

また、ビジネスルールで週が月曜日から始まると定められている場合は、-1から-2


編集

何年も経ちましたが、ついにこれを書き始めました。 http://www.plumislandmedia.net/mysql/sql-reporting-time-intervals/

25
O. Jones

YEAR(timestamp)WEEK(timestamp) の両方を使用し、SELECTと_GROUP BY_句。

過度にエレガントではなく、機能的...

そしてもちろん、これら2つの日付部分を単一の式に結合することもできます。

_SELECT CONCAT(YEAR(timestamp), '/', WEEK(timestamp)), etc...
FROM ...
WHERE ..
GROUP BY CONCAT(YEAR(timestamp), '/', WEEK(timestamp))
_

Edit:As Martin points out を使用することもできます YEARWEEK(mysqldatefield) ただし、その出力は上記の長い式ほど目に優しいものではありません。


Edit 2[3年半後!]:
YEARWEEK(mysqldatefield) オプションの2番目の引数( mode )を0または2に設定するのがおそらく最良の方法ですcomplete週(つまり、1月1日にまたがる週を含む)ごとに集計すること(必要な場合)。この回答で最初に提案されたYEAR() / WEEK()アプローチは、そのような "straddling"週の集約データを2つに分割する効果があります。新しい年に。
毎年2回の部分的な週(両端の1週間)を費やすクリーンカットは、会計などで必要とされることが多く、そのためにはYEAR() / WEEK()アプローチの方が適しています。

102
mjv

上記の受け入れられた答えは、私にとってはうまくいきませんでした。

2012/1
2012/10
2012/11
...
2012/19
2012/2

週ごとにカウントおよびグループ化する私のソリューションは次のとおりです。

SELECT CONCAT(YEAR(date), '/', WEEK(date)) AS week_name, 
       YEAR(date), WEEK(date), COUNT(*)
FROM column_name
GROUP BY week_name
ORDER BY YEAR(DATE) ASC, WEEK(date) ASC

生成:

YEAR/WEEK   YEAR   WEEK   COUNT
2011/51     2011    51      15
2011/52     2011    52      14
2012/1      2012    1       20
2012/2      2012    2       14
2012/3      2012    3       19
2012/4      2012    4       19
26
B Seven

YEARWEEK() 関数を使用して、連結された年と週の番号(200945)を取得できます。あなたの目標を正しく理解していれば、複数年のデータをグループ化できます。

週の初めに実際のタイムスタンプが必要な場合、それはニースではありません:

DATE_SUB( field, INTERVAL DAYOFWEEK( field ) - 1 DAY )

毎月の順序については、 LAST_DAY() 関数を検討するかもしれません-ソートは月の最終日までになりますが、それは月の最初の日までにソートするのと同等でなければなりません... ?

22
martin clayton

これをselectで広告するだけです:

DATE_FORMAT($yourDate, \'%X %V\') as week

そして

group_by(week);
4
Xavier

「週末」の日付が必要な場合、これも同様に機能します。これにより、各週のレコード数がカウントされます。例:2010年1月9日から2010年1月9日までの間に2010年1月9日から2010年8月1日までの間に3つの作業指示書が作成された場合

3 2010年1月8日
5 2010年1月16日

日付時刻フィールドを切り捨てるには、追加のDATE()関数を使用する必要がありました。

SELECT COUNT(*), DATE_ADD( DATE(wo.date_created), INTERVAL (7 - DAYOFWEEK( wo.date_created )) DAY) week_ending FROM work_order wo GROUP BY week_ending;

2
Randy