【问题标题】:How to select data from multiple tables based on different time ranges?如何根据不同的时间范围从多个表中选择数据?
【发布时间】:2014-10-02 10:11:55
【问题描述】:

我在 MySQL 中有两个表:

  • 访问次数

visits 表如下所示:

+-------+-------------------+-----------+
|   id  |   date            |  user_id  |
+-------+-------------------+-----------+
|   1   |2014-08-01 05:23:00|       43  |
|   2   |2014-08-01 14:41:00|       21  |
|   3   |2014-08-02 23:54:00|       43  |
|   4   |2014-08-03 03:21:00|       43  |
|   5   |2014-08-03 04:19:00|       34  |
|   6   |2014-08-03 11:33:00|       43  |
|   7   |2014-08-04 12:21:00|       43  |
|   8   |2014-08-05 01:55:00|       43  |
|   9   |2014-08-06 06:13:00|       43  |
|  10   |2014-08-07 19:47:00|       43  |
+-------+-------------------+-----------+

points 表如下所示:

+-------+-------------------+-----------+-------+----------+
|   id  |   date            |  user_id  | points|   status |
+-------+-------------------+-----------+-------+----------+
|   1   |2014-08-01 04:33:00|       43  |   10  |        0 |
|   2   |2014-08-02 05:21:00|       21  |   23  |        0 |
|   3   |2014-08-02 09:01:00|       43  |   32  |        1 |
|   4   |2014-08-02 01:21:00|       43  |   21  |        0 |
|   5   |2014-08-03 23:23:00|       34  |   54  |        0 |
|   6   |2014-08-04 20:34:00|       43  |   11  |        0 |
|   7   |2014-08-04 17:54:00|       43  |    9  |        0 |
|   8   |2014-08-04 03:45:00|       43  |   34  |        0 |
|   9   |2014-08-06 08:23:00|       43  |   76  |        0 |
|  10   |2014-08-07 11:43:00|       43  |   52  |        0 |
+-------+-------------------+-----------+-------+----------+

我只想执行 1 个查询并实现以下目标。

我想countvisits 表中user_id = 43date 介于2014-08-012014-08-03 之间的行。

我还想count 行,points 表中的points points,其中user_id = 43date2014-08-012014-08-03 之间,状态为0。

之后,在同一个查询中,我想选择与上面相同的查询,但在不同的时间范围内,例如:2014-08-042014-08-07

有没有可以为我解决这个问题的查询?

(我实际上这样做是因为我想为我的 jQuery 图表之一获取数据:Morris.js。如果访问者选择一个时间范围并将其划分,我想获取 12 个数据集根据访问者选择的日期。例如:如果他选择:2014-08-01 到 2014-08-01,我想向他显示当天的 12 个数据集。但是如果他选择例如:2014-08- 01 到 2014-08-06,然后我想向他显示 6 天除以 12 的数据。)

如果您不明白这里的某些内容,请告诉我,我会更好地解释它。关键是我想收集数据集并根据访问者的时间范围绘制图表。上面的 MySQL 逻辑是解决我问题的好方法吗?

编辑:

根据要求,我在此处显示所需的结果:

+---------------------+-----------+-------+-------+-------------+
|   date              |  user_id  | points| visits| points_count|
+---------------------+-----------+-------+-------+-------------+
|2014-08-01-2014-08-03|     43    | 31    | 4     | 2           |
|2014-08-04-2014-08-07|     43    | 182   | 4     | 5           |
+---------------------+-----------+-------+-------+-------------+

我希望我计算正确。

【问题讨论】:

  • 请编辑您的问题并为您提供的样本数据显示您想要的结果。
  • 好的,请稍等。
  • @GordonLinoff 问题已更新。
  • @Radical_Activity 我刚刚发布了一个查询,它将完全按照您的要求以及一个演示来显示它的工作原理:)

标签: php jquery mysql sql charts


【解决方案1】:

你可以试试:

select count(id)
from visits
join points on points.user_id = visits.user_id
where date between 2014-08-04 00:00:00 and 2014-08-07 00:00:00
and visits.user_id = 43

【讨论】:

    【解决方案2】:

    更好的选择可能是实际使用存储过程并设置开始日期参数和结束日期参数,以便您可以选择所需的任何日期

    【讨论】:

      【解决方案3】:

      想到的唯一方法是执行两个不同的查询并使用UNION ALL

      SELECT *
      FROM
        (SELECT 
          count(v.id) AS visit_count, 
          count(p.id) AS point_count, 
          sum(p.points) AS points
        FROM visits v1
        JOIN points p1
        ON v1.user_id = p1.user_id
        WHERE v1.user_id = 43
        AND DATE(v1.date) BETWEEN '2014-08-01' AND '2014-08-03'
        AND p1.status = 0
        UNION ALL
        SELECT 
          count(v.id) AS visit_count, 
          count(p.id) AS point_count, 
          sum(p.points) AS points
        FROM visits v2
        JOIN points p2
        ON v2.user_id = p2.user_id
        WHERE v2.user_id = 43
        AND DATE(v2.date) BETWEEN '2014-08-04' AND '2014-08-07'
        AND p2.status = 0
      ) temp
      

      【讨论】:

      • 这看起来不错,但是如果我要创建 12 个这样的查询呢?我猜这将是一个相当广泛的内容。
      • 是的,如果我没记错的话(我希望其他人会这么说)联合所有查询就像运行两个单独的查询一样,并且根据您的数据集可能很昂贵,也许其他人可以想出一个更好的解决方案。
      • 条件分组怎么样?我认为这会起作用..看看我发布的例子
      • 我也认为条件分组是这里的最佳选择。
      【解决方案4】:

      好的,所以这需要做一些工作,因为您必须彼此独立地连接两个表。原因是因为一个不能具有 1 的状态,而另一个可以..因此请记住此查询将完全返回您想要的。

      查询:

      SELECT 
          t.join_date as 'Time Frame',
          t1.user_id,
          t.num_visits,
          t1.num_points,
          t1.total_points
      FROM
      (   SELECT 
              CASE 
                  WHEN DATE(date) >= '2014-06-01' AND DATE(date) <= '2014-07-10' THEN 1 
                  WHEN DATE(date) >= '2014-08-05' AND DATE(date) <= '2014-08-07' THEN 2 
                  ELSE 3
              END AS grouping_col,
              CONCAT(MIN(DATE(date)), ' - ', MAX(DATE(date))) as join_date,
              COUNT(id) as num_visits 
          FROM visits 
          WHERE user_id = 43
          GROUP BY grouping_col 
      )t
      LEFT JOIN 
      (   SELECT
              CASE 
                  WHEN DATE(date) >= '2014-06-01' AND DATE(date) <= '2014-07-10' THEN 1 
                  WHEN DATE(date) >= '2014-08-05' AND DATE(date) <= '2014-08-07' THEN 2 
                  ELSE 3
              END AS grouping_col,
              CONCAT(MIN(DATE(date)), ' - ', MAX(DATE(date))) as join_date,
              user_id,
              COUNT(id) as num_points,
              SUM(points) as total_points
          FROM points
          WHERE user_id = 43
            AND status = 0
          GROUP BY grouping_col
      )t1 ON t1.grouping_col = t.grouping_col
      WHERE t.grouping_col IN(1, 2) OR t1.grouping_col IN(1, 2)
      

      注意:

      您可以通过在 CASE 语句中添加更多行来添加尽可能多的时间范围...

      观看演示:

      FIDDLE

      【讨论】:

      • 非常感谢您的询问。老实说,这是最接近完美的一个,但它有一些问题,因为我已经用日期测试过。如果我在查询中更改日期,它会返回错误的结果。我想那里缺少一些东西。你能帮我仔细检查一下吗? :)
      • @Radical_Activity 你包括什么日期,它是什么样的?你需要在 case 语句中添加一个新的日期范围。复制其中一行并做同样的事情,除了让 THEN 部分为每一行增加
      • @Radical_Activity 如果您可以使用您正在使用的确切查询编辑您的问题,我可以查看它。
      • 我说的是你的小提琴。尝试更改日期,例如在两个地方将第二个日期从 2014-08-04 更改为 2014-08-05。它返回 3 个结果。此外,当我玩过这些日期时,它也给了我奇怪的结果。我也用我的数据尝试过,2014-08-04 - 2014-08-07 给了我来自2014-07-26point 记录和来自2014-07-21visits。我正在使用与您的小提琴所包含的完全相同的查询。
      • @Radical_Activity 哦,好吧,对不起,我在查询中犯了一个错误。一秒钟我正在更新它。
      猜你喜欢
      • 1970-01-01
      • 2022-08-18
      • 2021-11-21
      • 2017-12-30
      • 2013-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-10
      相关资源
      最近更新 更多