sql >> データベース >  >> RDS >> Mysql

MySQL-月ごとにカウント(欠落しているレコードを含む)

    必要なすべての日付を生成してから、データを日付に結合したままにする必要があります。左側の結合のONにいくつかの述語を入れることが重要であることにも注意してください。 WHEREの句など 条項:

    SELECT
      CONCAT(y, '-', LPAD(m, 2, '0')) as byMonth,
      COUNT(`created`) AS Total 
    FROM (
      SELECT year(now())     AS y UNION ALL
      SELECT year(now()) - 1 AS y 
    ) `years`
    CROSS JOIN (
      SELECT  1 AS m UNION ALL
      SELECT  2 AS m UNION ALL
      SELECT  3 AS m UNION ALL
      SELECT  4 AS m UNION ALL
      SELECT  5 AS m UNION ALL
      SELECT  6 AS m UNION ALL
      SELECT  7 AS m UNION ALL
      SELECT  8 AS m UNION ALL
      SELECT  9 AS m UNION ALL
      SELECT 10 AS m UNION ALL
      SELECT 11 AS m UNION ALL
      SELECT 12 AS m
    ) `months`
    LEFT JOIN `qualitaet` q
    ON YEAR(`created`) = y 
      AND MONTH(`created`) = m
      AND `status` = 1
    WHERE STR_TO_DATE(CONCAT(y, '-', m, '-01'), '%Y-%m-%d') 
        >= MAKEDATE(year(now()-interval 1 year),1) + interval 5 month
      AND STR_TO_DATE(CONCAT(y, '-', m, '-01'), '%Y-%m-%d') 
        <= now()
    GROUP BY y, m
    ORDER BY y, m
    

    上記はどのように機能しますか?

    • CROSS JOIN デカルト積 を作成します 利用可能なすべての年と利用可能なすべての月の間。これはあなたが望むものであり、ギャップのないすべての年月の組み合わせが必要です。
    • LEFT JOIN すべてのqualitaetを追加します 結果を記録し(存在する場合)、前からの年月のデカルト積に結合します。 status = 1のようなprediactsを配置することが重要です ここに述語があります。
    • COUNT(created) createdのNULL以外の値のみをカウントします 、つまり、LEFT JOIN 特定の年月に行を生成しないため、0が必要です 結果として、1ではありません 、つまり、NULLをカウントしたくない 値。

    パフォーマンスに関する注意

    上記は、ONで文字列演算と日時演算を多用しています。 およびWHERE 述語。これは、大量のデータに対しては機能しません。その場合は、qualitaetで年月を事前に切り捨てて、インデックスを作成することをお勧めします。 テーブルを作成し、それらの値のみを操作します。




    1. mysqlから数値データのみを選択する方法は?

    2. mysqlを使用して日付がdate1とdate2の間にあるかどうかを確認するにはどうすればよいですか?

    3. pg_viewsのクエリからの不完全な情報

    4. 時間部分を無視してDATETIMEとDATEを比較します