Mysql 请提供复杂的SQL查询建议

Mysql 请提供复杂的SQL查询建议,mysql,sql,Mysql,Sql,我有三个表,模式如下: 表:应用程序 | ID (bigint) | USERID (Bigint)| START_TIME (datetime) | ------------------------------------------------------------- | 1 | 13 | 2013-05-03 04:42:55 | | 2 | 13 | 201

我有三个表,模式如下:

表:应用程序

| 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) | 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”的每月(所有应用程序)表行的计数

如果设备ID每月出现一次以上(基于开始时间,基于加入应用程序和主机),则计算计数时仅考虑最新的使用情况行(基于应用程序、主机和使用情况的组合)

上述示例的查询输出示例应为:(对于输入用户id=13)

这是如何计算的?

  • 2013年5月(2013年5月),有两个应用程序来自表格应用程序
  • 在表主机中,这些应用程序与设备id的1,1,1,4,3相关联
  • 对于本月(2013年5月),对于设备_id=1,开始_时间的最新值为:2013-05-12 06:22:45(来自表主机、应用程序),因此在表用法中,查找appid=2和hostid=2的组合,其中有两行,一行系数低,另一行系数中等
  • 对于本月(2013年5月),对于设备_id=4,通过遵循相同的程序,我们得到一个条目,即0低
  • 同样,所有的值都是计算出来的
  • 为了通过查询获取过去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:

    因为您正在进行的计算多次涉及相同的连接,所以我从创建视图开始

    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
    

    这非常复杂,但我试着解释一下每个部分的作用。请参阅此SQLFIDLE:

    您可能需要编辑以澄清此问题。我的答案和@ubik404都可能是有效的,具体取决于您想要的行为。@Dan我只能看到您的答案。我正在测试它。谢谢,非常感谢,丹。我正在测试这个查询。@Dan我想计算每个月不同设备的使用时间,但是这个查询给了我设备的数量,你能帮忙吗?@sash对你要找的东西没有更清楚的了解。有太多的方法来解释您的需求。这是一种可能性。