4

私はMySQLを使用しており、次のuser_dataようなテーブルがあります。

user_id         int(10) unsigned
reg_date        int(10) unsigned
carrier         char(1)

reg_dataは、登録時刻のUNIXタイムスタンプ(1日の任意の秒である可能性があります)であり、キャリアはキャリアのタイプであり、可能な値は「D」、「A」、または「V」のみです。

2013/01/01から2013/01/31までの毎日のさまざまなキャリアの登録ユーザー番号を選択するSQLステートメントを作成する必要があります。したがって、望ましい結果は次のようになります。

2013/01/01   D   10
2013/01/01   A   31
2013/01/01   V   24
2013/01/02   D    9
2013/01/02   A   23
2013/01/02   V   14
....
2013/01/31   D   11
2013/01/31   A   34
2013/01/31   V   22

誰かがこの質問で私を助けることができますか?最良の答えを出す必要があります。つまり、必要に応じてインデックスを追加できますが、クエリを効率的に保つ必要があります。

現在、(reg_date、carrier)にインデックスを作成し、次のクエリを使用しています。

select FROM_UNIXTIME(reg_date, "%M %D %Y") as reg_day, carrier, count(carrier) as user_count
from user_data
where reg_date >= UNIX_TIMESTAMP('2013-01-01 00:00:00') and reg_date < UNIX_TIMESTAMP('2013-02-01 00:00:00')
group by reg_day, carrier
order by reg_date;

ありがとう!

4

1 に答える 1

1

テーブルを変更できない場合(個々の日付を保存すると少し役立ちます)、インデックスを作成するだけで、次のようになります。

複合インデックスを作成します。carrier, reg_date次に、グループcarrier, reg_date化して並べ替えreg_date, carrierます。

タイムスタンプ専用に他のインデックスを作成できます(スコープ外のレコード数によっては、WHERE計算の方がうまくいく場合があります)。

さらに、完全にUNIXタイムスタンプを使用し、これをサブクエリとして埋め込むことができます。外部のタイムスタンプは、タイムスタンプを人間が読める形式の日付に変換できます(このように、変換は、個々のレコードごとではなく、グループの後で行われます)。

インデックスの作成:

CREATE INDEX bytime ON user_data (reg_date);
CREATE INDEX daily_group ON user_data (carrier, reg_date);

クエリ:

SELECT FROM_UNIXTIME(reg_day, "%M %D %Y") AS reg_day
    , carrier
    , user_count
FROM (
    SELECT FLOOR(reg_date / (60 * 60 * 24)) AS reg_day
        , carrier
        , count(carrier) AS user_count
    FROM user_data
    WHERE reg_date >= UNIX_TIMESTAMP('2013-01-01 00:00:00')
        AND reg_date < UNIX_TIMESTAMP('2013-02-01 00:00:00')
    GROUP BY carrier, reg_day
    ORDER BY reg_day, carrier
    ) AS a;
于 2013-03-25T09:21:42.677 に答える