1

私は毎月の結果の数を数えようとしています。

これは私の質問です:

SELECT 
    COUNT(*) as nb,
    CONCAT(MONTH(t.date),0x3a,YEAR(t.date)) as period
FROM table1 t
WHERE t.criteria = 'value'
GROUP BY MONTH(t.date)
ORDER BY YEAR(t.date)

私の結果:

nb  period
---------------
7   6:2009
46  8:2009
2   10:2009
1   11:2009
14  1:2009
9   9:2010
161 7:2010
5   2:2010
88  3:2010
28  4:2010
4   5:2011
2   12:2011

問題は、私が5:2011と12:2011の間、および2009年以降の各期間の結果であると確信していることです...:/

これは私のリクエストまたはmysql設定の問題ですか?

ありがとう

4

2 に答える 2

3

年と月の両方でグループ化する必要があります。それ以外の場合、2012年4月の行は2011年4月(および2010年4月...)の行とグループ化されます。

SELECT 
    COUNT(*) AS nb,
    CONCAT(MONTH(t.date), ':', YEAR(t.date)) AS period
FROM table1 AS t
WHERE t.criteria = 'value'
GROUP BY YEAR(t.date)
       , MONTH(t.date) ;

0x3a(そして、あなたが使用したのに使用しなかった理由はあります':'か?)


MySQLの他のDATE関数とTIME関数を使用して、行ごとの関数呼び出しを減らし、おそらくより効率的なクエリを実行することもできます。

SELECT 
    COUNT(*) AS nb,
    DATE_FORMAT(t.date, '%m:%Y') AS period
FROM table1 AS t
WHERE t.criteria = 'value'
GROUP BY EXTRACT( YEAR_MONTH FROM t.date) ;

いくつかのクエリでは、データベースに永続的なカレンダーテーブル(すべての日付またはすべての年月)または複数のカレンダーテーブルがあると便利です。例:

CREATE TABLE CalendarYear
  ( Year SMALLINT UNSIGNED NOT NULL
  , PRIMARY KEY (Year)
  ) ENGINE = InnoDB ;

INSERT INTO CalendarYear
  (Year)
VALUES
  (1900), (1901), ..., (2099) ;

CREATE TABLE CalendarMonth
  ( Month TINYINT UNSIGNED NOT NULL
  , PRIMARY KEY (Month)
  ) ENGINE = InnoDB ;

INSERT INTO CalendarMonth
  (Month)
VALUES
  (1), (2), ..., (12) ;

これらは、ここで必要なものを作成するのにも役立ちます。

CREATE TABLE CalendarYearMonth
  ( Year SMALLINT UNSIGNED NOT NULL
  , Month TINYINT UNSIGNED NOT NULL
  , FirstDay DATE NOT NULL
  , NextMonth_FirstDay DATE NOT NULL
  , PRIMARY KEY (Year, Month)
  ) ENGINE = InnoDB ;

INSERT INTO CalendarYearMonth
  (Year, Month, FirstDay, NextMonth_FirstDay)
SELECT
    y.Year
  , m.Month
  , MAKEDATE(y.Year, 1) + INTERVAL (m.Month-1) MONTH
  , MAKEDATE(y.Year, 1) + INTERVAL (m.Month) MONTH
FROM
    CalendarYear AS y
  CROSS JOIN
    CalendarMonth AS m ;

次に、カレンダーテーブルを使用して、必要なバリエーション(月が欠落している)などのより複雑なクエリを、おそらくより効率的に作成できます。SQLでテスト済み-フィドル

SELECT 
    COUNT(t.date) AS nb,
    CONCAT(cal.Month, ':', cal.Year) AS period
FROM
        CalendarYearMonth AS cal
    JOIN
        ( SELECT
              YEAR(MIN(date))  AS min_year
            , MONTH(MIN(date)) AS min_month
            , YEAR(MAX(date))  AS max_year
            , MONTH(MAX(date)) AS max_month
          FROM table1
          WHERE criteria = 'value'
        ) AS mm
      ON  (cal.Year, cal.Month) >= (mm.min_year, mm.min_month)
      AND (cal.Year, cal.Month) <= (mm.max_year, mm.max_month)
    LEFT JOIN
        table1 AS t
      ON  t.criteria = 'value'
      AND t.date >= cal.FirstDay
      AND t.date < cal.NextMonth_FirstDay
GROUP BY 
    cal.Year, cal.Month ;
于 2012-09-26T08:02:57.400 に答える
2

あなたはまたGROUP BY年でなければなりません:

GROUP BY MONTH(t.date), YEAR(t.date)

元のクエリはYEAR(t.date)SELECT集計関数の外部の句でグループ化せずに使用します。その結果、正確に12のグループ(可能な月ごとに1つ)と各グループ(おそらく何年にもわたる日付を含む)に対して「ランダム」を取得します。 "年はMySqlによって選択されます。厳密に言えば、これは無意味であり、クエリの実行を許可するべきではありませんでした。しかし、MySql...ため息をつきます。

于 2012-09-26T08:01:53.807 に答える