0

ユーザーがページを開くたびにユーザーIDタイムスタンプを含むテーブルがあり、新しいフィールドが挿入されます。

複数のユーザーの 1 か月間隔で表示される時間///の合計量を取得しようとしています。

さまざまなクエリを試しましたが、どれも非常に非効率的でした。

理想的には、次のようなものになりたいです。

   userid | minutes | hours | days | weeks
      1      10080     168      7      1
      2       1440      24      1      0

うまくいけば、誰かがこれを行う方法に光を当てることができます。

以下は私が試したクエリです:

  SELECT 
    w.time AS `week`, 
    d.time AS `day`, 
    h.time AS `hour`, 
    m.time AS `minutes`
    FROM (
             SELECT 
            SUM( t.time ) AS `time`
             FROM (
                    SELECT 
                    COUNT( DISTINCT WEEK( `timestamp` ) ) AS `time`
                FROM table
                    WHERE 
                    userid =  "1"
                    AND 
                    `timestamp` > DATE_SUB( NOW( ) , INTERVAL 1 MONTH ) 
                    GROUP BY MONTH( `timestamp` )
                    ) t
         ) w, 
        (
             SELECT 
            SUM( t.time ) AS `time`
             FROM (
                    SELECT 
                    COUNT( DISTINCT DAY( `timestamp` ) ) AS `time`
                    FROM table
                    WHERE 
                    userid =  "52"
                    AND 
                    `timestamp` > DATE_SUB( NOW( ) , INTERVAL 1 MONTH ) 
                    GROUP BY MONTH( `timestamp` )
             ) t
            ) d,
         (
        SELECT 
            SUM( t.timestamp ) AS `time`
            FROM (
                SELECT 
                    COUNT( DISTINCT HOUR( `timestamp` ) ) AS `time`
                    FROM table
                    WHERE 
                    userid =  "1"
                    AND 
                    `timestamp` > DATE_SUB( NOW( ) , INTERVAL 1 MONTH ) 
                GROUP BY DAY( `timestamp` )
                 ) t
            ) h, 
        (
            SELECT 
            SUM( t.timestamp ) AS `time`
            FROM (
                SELECT 
                    COUNT( DISTINCT MINUTE( `timestamp` ) ) AS `time`
                 FROM table
                WHERE 
                    userid =  "1"
                AND 
                    `timestamp` > DATE_SUB( NOW( ) , INTERVAL 1 MONTH ) 
                    GROUP BY HOUR( `timestamp` )
             ) t
         ) m

このタスクには非常に過剰に思えますが、誰かがもっと良いものを持っているのではないでしょうか?

4

2 に答える 2

1

あなたが「合計」したいものは私には明らかではありません。

ユーザーがその月の特定の分に「ヒット」(またはテーブルに保存しているトランザクション)を行ったかどうかを判断したい場合、ユーザーがヒットした月:

 SELECT t.userid
      , COUNT(DISTINCT DATE_FORMAT(t.timestamp,'%Y-%m-%d %H:%i')) AS minutes
      , COUNT(DISTINCT DATE_FORMAT(t.timestamp,'%Y-%m-%d %H'   )) AS hours
      , COUNT(DISTINCT DATE_FORMAT(t.timestamp,'%Y-%m-%d'      )) AS days
      , COUNT(DISTINCT DATE_FORMAT(t.timestamp,'%X-%V'         )) AS weeks
 FROM mytable t
WHERE t.timestamp >= '2012-06-01'
  AND t.timestamp <  '2012=07-01'
GROUP BY t.userid 

これが行っていることは、各タイムスタンプを取得し、秒を切り刻む、分を切り刻む、時間を切り刻むなどして「バケット」に入れることです。

基本的に、タイムスタンプ (例: '2012-07-25 23:15:30') を取得し、それを

minute '2012-07-25 23:15'
hour   '2012-07-25 23'
day    '2012-07-25'

のタイムスタンプが '2012-07-25 23:25:00'割り当てられます

minute '2012-07-25 23:25'
hour   '2012-07-25 23'
day    '2012-07-25'

次に、タイムスタンプを割り当てた個別のバケットの数を数えます。このユーザーの 1 か月のヒット数がこれだけの場合、クエリは分数を表す 2 を返し、他のすべての期間数を表す 1 を返します。

その月に 1 回のヒットがあったユーザーの場合、そのユーザーのすべてのカウントは 1 になります。

まったく同じ 1 分間にすべての「ヒット」を記録したユーザーの場合、クエリは再びすべてのカウントに対して 1 を返します。

(1 か月以内に "ヒット" がないユーザーの場合、行は返されません。(ゼロ カウントを返したい場合は、ユーザーのリストを取得するために別の行ソースに参加する必要があります。)

1 日に 1 秒ごとに「ヒット」したユーザーの場合、このクエリは、例のユーザー ID 2 に示されているようなカウントを返します。

この結果セットは、1 か月間のユーザーのアクティビティの一種の指標を提供します... ユーザーが 1 か月間にアクティブだった「分期間」の数。

「days」に返される可能性のある最大の値は、その月の日数です。"hours" に返される可能性のある最大値は、月の日数の 24 倍になります。「分」に返される最大値は、月の日数の 1440 倍です。

しかし、繰り返しになりますが、どの結果セットを返したいのかは完全にはわかりません。しかし、これは以前に「選択した」回答からのものよりもはるかに合理的な結果セットのようです。

于 2012-07-27T05:40:06.143 に答える
1
SELECT userid, SUM(MINUTE(timestamp)) AS minutes, SUM(MINUTE(timestamp))/60 AS hours, SUM(MINUTE(timestamp))/(60*24) AS days, SUM(MINUTE(timestamp))/(60*24*7) AS weeks
FROM Table
GROUP BY userid

ROUND(SUM(MINUTE(timestamp)), 0)必要に応じて、整数が必要な場合に使用します。

于 2012-07-27T03:47:06.107 に答える