2

以下のようなスキーマを持つ 3 つのテーブルがあります。

表:アプリ

| ID (bigint) | USERID (Bigint)|      START_TIME (datetime) | 
-------------------------------------------------------------
|  1          |        13     |         2013-05-03 04:42:55 | 
|  2          |        13     |         2013-05-12 06:22:45 |
|  3          |        13     |         2013-06-12 08:44:24 |    
|  4          |        13     |         2013-06-24 04:20:56 |       
|  5          |        13     |         2013-06-26 08:20:26 |       
|  6          |        13     |         2013-09-12 05:48:27 | 

表:ホスト

| ID (bigint) | APPID (Bigint)|         DEVICE_ID (Bigint)  | 
-------------------------------------------------------------
|  1          |        1      |                           1 | 
|  2          |        2      |                           1 |
|  3          |        1      |                           1 |    
|  4          |        3      |                           3 |       
|  5          |        1      |                           4 |      
|  6          |        2      |                           3 |

表: 使用法

| ID (bigint) | APPID (Bigint)|             HOSTID (Bigint) |   Factor (varchar)    |  
-------------------------------------------------------------------------------------
|  1          |        1      |                           1 |               Low     | 
|  2          |        1      |                           3 |               High    | 
|  3          |        2      |                           2 |               Low     | 
|  4          |        3      |                           4 |               Medium  | 
|  5          |        1      |                           5 |               Low     | 
|  6          |        2      |                           2 |               Medium  | 

put が userid の場合、過去 6 か月間の "Factor" 月ごとに (すべてのアプリの) 各月のテーブル行の行数を取得したいと考えています。

DEVICE_ID が 1 か月に複数回 (START_TIME に基づいて、アプリとホストの参加に基づいて) 表示される場合、カウントの計算では (アプリ、ホスト、および使用状況の組み合わせに基づいて) 使用状況の最新の行のみが考慮されます。

上記の例のクエリの出力例は次のようになります: (入力ユーザー ID=13 の場合)

| MONTH       | USAGE_COUNT   |               FACTOR        | 
-------------------------------------------------------------
|  5          |        0      |                 High        | 
|  6          |        0      |                 High        | 
|  7          |        0      |                 High        | 
|  8          |        0      |                 High        |       
|  9          |        0      |                 High        |       
|  10         |        0      |                 High        | 
|  5          |        2      |                 Low         | 
|  6          |        0      |                 Low         | 
|  7          |        0      |                 Low         | 
|  8          |        0      |                 Low         |       
|  9          |        0      |                 Low         |       
|  10         |        0      |                 Low         |
|  5          |        1      |                 Medium      | 
|  6          |        1      |                 Medium      | 
|  7          |        0      |                 Medium      | 
|  8          |        0      |                 Medium      |       
|  9          |        0      |                 Medium      |       
|  10         |        0      |                 Medium      |

これはどのように計算されますか?

  1. 2013 年 5 月 (05-2013) の月には、テーブル アプリから 2 つのアプリがあります。
  2. テーブル Hosts では、これらのアプリは device_id の 1,1,1,4,3 に関連付けられています。
  3. 今月 (2013 年 5 月) の device_id=1 の場合、start_time の最新の値は 2013-05-12 06:22:45 (hosts,apps テーブルから) であるため、Usage テーブルで appid=2&hostid の組み合わせを探します。 =2 の 2 つの行があり、1 つは係数が低で、もう 1 つは中です。
  4. 今月 (2013 年 5 月) の device_id=4 については、同じ手順に従って 1 つのエントリ、つまり 0 Low を取得します。
  5. 同様に、すべての値が計算されます。

クエリを介して過去 6 か月を取得するには、次のようにして取得しようとしています。

SELECT MONTH(DATE_ADD(NOW(), INTERVAL aInt MONTH)) AS aMonth
    FROM
    (
        SELECT 0 AS aInt UNION SELECT -1 UNION SELECT -2 UNION SELECT -3 UNION SELECT -4 UNION SELECT -5
    ) 

sqlfiddle を確認してください: http://sqlfiddle.com/#!2/55fc2

4

1 に答える 1

1

あなたが行っている計算には同じ結合が複数回含まれているため、ビューを作成することから始めました。

CREATE VIEW `app_host_usage`
AS 
SELECT a.id "appid", h.id "hostid", u.id "usageid",
       a.userid, a.start_time, h.device_id, u.factor
  FROM apps a
  LEFT OUTER JOIN hosts h ON h.appid = a.id
  LEFT OUTER JOIN `usage` u ON u.appid = a.id AND u.hostid = h.id
  WHERE a.start_time > DATE_ADD(NOW(), INTERVAL -7 MONTH)

条件が存在するのWHEREは、2005 年 7 月と 2006 年 7 月を同じカウントにグループ化することは望ましくないと仮定したためです。

そのビューを配置すると、クエリは次のようになります

SELECT months.Month, COUNT(DISTINCT device_id), factors.factor
FROM
  (
    -- Get the last six months
    SELECT (MONTH(NOW()) + aInt + 11) % 12 + 1 "Month" FROM
      (SELECT 0 AS aInt UNION SELECT -1 UNION SELECT -2 UNION SELECT -3 UNION SELECT -4 UNION SELECT -5) LastSix
  ) months
  JOIN
  ( 
    -- Get all known factors
    SELECT DISTINCT factor FROM `usage` 
  ) factors
  LEFT OUTER JOIN
  (
    -- Get factors for each device... 
    SELECT 
           MONTH(start_time) "Month", 
           device_id,
           factor
      FROM app_host_usage a
      WHERE userid=13 
        AND start_time IN (
          -- ...where the corresponding usage row is connected
          --    to an app row with the highest start time of the
          --    month for that device.
          SELECT MAX(start_time)
            FROM app_host_usage a2
            WHERE a2.device_id = a.device_id
            GROUP BY MONTH(start_time)
        )
     GROUP BY MONTH(start_time), device_id, factor

  ) usageids ON usageids.Month = months.Month 
            AND usageids.factor = factors.factor
GROUP BY factors.factor, months.Month
ORDER BY factors.factor, months.Month

これはめちゃくちゃ複雑ですが、各部分が何をするのかを説明するためにコメントしようとしました。このsqlfiddleを参照してください:http://sqlfiddle.com/#!2/5c871/1/0

于 2013-10-06T22:28:25.957 に答える