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

MySQLの日付によるグループ化と欠落した日付を含むカウント

    OUTER JOINが必要です INNER JOINを使用すると、開始から終了までの間に毎日到着します。 結合された日付のみ(つまり、レポートテーブル内の日付のみ)に出力が制限されます。

    また、OUTER JOINを使用する場合 where clauseの条件に注意する必要があります implicit inner joinを引き起こさないでください;たとえば、 AND domain_id =1 where句で使用すると、その条件が満たされていない行は抑制されますが、結合条件として使用すると、レポートテーブルの行のみが制限されます。

    SELECT
          COUNT(r.domain_id)
        , all_dates.Date AS the_date
        , domain_id
    FROM (
            SELECT DATE_ADD(curdate(), INTERVAL 2 MONTH) - INTERVAL (a.a + (10 * b.a) ) DAY as Date
            FROM (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a
            CROSS JOIN (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b
          ) all_dates
          LEFT OUTER JOIN reports r
                      ON all_dates.Date = r.tracked_on
                            AND domain_id = 1
    WHERE all_dates.Date BETWEEN '2014-09-01' AND '2014-09-30'
    GROUP BY
          the_date
    ORDER BY
          the_date ASC;
    

    DATE_ADD()を使用して、all_dates派生テーブルも変更しました 出発点を未来に押し上げるために、私はそのサイズを縮小しました。これらは両方ともオプションであり、必要に応じて調整できます。

    SQLfiddleでのデモ

    (質問に示されているように)すべての行のdomain_idに到達するには、次のようなものを使用する必要があります。 IFNULL()を使用できることに注意してください これはMySQL固有ですが、COALESCE()を使用しました これはより一般的なSQLです。ただし、ここに示されている@parameterの使用は、とにかくMySQL固有です。

    SET @domain := 1;
    
    SELECT
          COUNT(r.domain_id)
        , all_dates.Date AS the_date
        , coalesce(domain_id,@domain) AS domain_id
    FROM (
            SELECT DATE_ADD(curdate(), INTERVAL 2 month) - INTERVAL (a.a + (10 * b.a) ) DAY as Date
            FROM (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a
            CROSS JOIN (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b
          ) all_dates
          LEFT JOIN reports r
                      ON all_dates.Date = r.tracked_on
                            AND domain_id = @domain
    WHERE all_dates.Date BETWEEN '2014-09-01' AND '2014-09-30'
    GROUP BY
          the_date
    ORDER BY
          the_date ASC;
    

    SQLfiddleでこれを参照



    1. SQLServerのSelectステートメントでNULL値を持つ行をフィルタリングする方法-SQLServer/TSQLチュートリアルパート110

    2. JavaからMySQLに画像を保存する

    3. 多数または未定義のカテゴリとのクロス集計

    4. PHPへのMySQLpassword()関数