【问题标题】:MYSQL: closest to supplied date grouped by user_idMYSQL:最接近按 user_id 分组的提供日期
【发布时间】:2015-09-10 01:36:07
【问题描述】:

我需要获取多行,其中 date_added 最接近但不超过用户提供的日期,按 user_id 分组。

我查看了一堆 max in group 类型的答案,但我不完全在那里:

Get nearest records to specific date grouped by type

SQL Query to show nearest date?

Find closest datetime to specified datetime in mysql query

Get closest date from MySQL table

https://dev.mysql.com/doc/refman/5.0/en/example-maximum-column-group-row.html

这很接近:https://stackoverflow.com/a/17038667/5319244。虽然找到最大日期,但我需要用户输入指定的最大值,而不是完全的最大值。

这是已过滤的具有正确组织 ID、框架 ID 和级别 ID 的数据子集。

+----+---------+-----------------+--------------+----------+---------------------+
| id | user_id | organisation_id | framework_id | level_id |     date_added      |
+----+---------+-----------------+--------------+----------+---------------------+
|  2 |       1 |               2 |            1 |        1 | 2015-07-31 14:02:49 |
|  9 |       2 |               2 |            1 |        1 | 2015-09-01 11:05:09 |
| 11 |       1 |               2 |            1 |        1 | 2015-09-07 14:13:39 |
+----+---------+-----------------+--------------+----------+---------------------+

如果提供的日期是 2015-09-07。我希望看到 id:9 和 11。

如果提供的日期是 2015-09-01。我希望看到 id:2 和 9。

如果提供的日期是 2015-07-31。我希望看到 id: 2。

这个查询和我得到的一样接近:

SELECT  t1.id
    , t1.user_id
    , t1.date_added 
FROM 
    completed_frameworks AS t1
WHERE date_added = (
    SELECT 
        MAX(date_added)
    FROM 
        completed_frameworks
    WHERE 
        user_id = t1.user_id
        AND 
        date_added <= '2015-09-07 23:59:59'
)
AND
(
    t1.organisation_id = 2 
    AND 
    t1.framework_id = 1 
    AND 
    t1.level_id = 1
)

它返回我对日期的期望:2015-09-07

当日期是 2015-09-01 但是它只返回 id 9。而不是我期望的 2。

当日期为 2015-07-31 时,它返回 0 行..

如果我还有什么可以提供的,请告诉我。

干杯!

编辑:

感谢到目前为止的回复。我需要澄清两点:

1) 我没有限制。由于用户 ID,我期待这些行。可能有 n 个用户返回。我只想为每个用户添加一行,其中 date_added 最接近用户提供的日期。

2) 提供的日期没有时间值。它将来自一个简单的日期选择器 UI。在我的示例查询中,我添加了 23:59:59 的时间来包含当天的所有时间。

【问题讨论】:

    标签: php mysql


    【解决方案1】:

    试试这个子查询。 organization_id/framework_id/level_id 过滤器被移到子查询中,现在它会为您给出的示例返回正确的值。

    SELECT t1.id, t1.user_id, t1.date_added 
    FROM 
        completed_frameworks AS t1
    WHERE date_added = (
        SELECT 
            MAX(date_added)
        FROM 
            completed_frameworks
        WHERE 
            user_id = t1.user_id
        AND 
            date_added <= '2015-09-01 23:59:59'
        AND
            organisation_id = 2 
        AND 
            framework_id = 1 
        AND 
            level_id = 1
    )
    

    【讨论】:

    • 我假设您实际上拥有的数据比您在子集中提供的数据多(赠品是我想的“子集”这个词),在这种情况下,子查询可能会返回数据,然后这些数据将被过滤掉最后的“WHERE”语句(例如,如果最近添加的记录是针对那些查询的框架或级别之外的)。
    【解决方案2】:

    这是一个示例查询,您可以将其用于'2015-09-07 14:13:39' 的输入日期。内部查询返回输入日期以及下一个最高日期。然后使用这个临时表过滤completed_frameworks,只为您提供距输入日期最近的两个日期的记录。

    SELECT t1.id, t1.user_id, t1.date_added
    FROM completed_frameworks t1
    INNER JOIN
    (
        SELECT cf.date_added
        FROM completed_frameworks cf
        GROUP BY cf.date_added
        HAVING cf.date_added <= '2015-09-07 14:13:39'
        ORDER BY cf.date_added DESC
        LIMIT 2
    ) t2
    ON t1.date_added = t2.date_added
    WHERE t1.organisation_id = 2 AND t1.framework_id = 1 AND t1.level_id = 1
    

    【讨论】:

      【解决方案3】:

      我认为这是你想要的:

      SELECT f.id, f.user_id  f.date_added 
      FROM completed_frameworks f
      WHERE date(f.date_added) <= '2025-09-07'  -- or whatever your date is
      ORDER BY f.date_added DESC
      LIMIT 2;
      

      编辑:

      如果您希望每个用户 ID 有一个最接近指定日期的日期,我建议:

      select f.*
      from completed_frameworks f join
           (select user_id, max(date_added) as maxda
            from completed_frameworks
            where date(date_added) <= '2015-09-07'
            group by user_id
           ) u
           on f.user_id = u.user_id and f.date_added = maxda
      

      【讨论】:

      • 你知道的比我多,但我担心他的实际数据集每个日期可能有多个记录。
      • @TimBiegeleisen 。 . .我不确定这与它有什么关系。这将检索最近的 2 个条目。
      • 谢谢大家。为了更清楚,我已经编辑了这个问题。没有限制。预期的结果是由于 user_ids。我不是在寻找最近的两个。
      • @LGH 。 . .哦,这个问题完全不同。
      猜你喜欢
      • 2016-07-07
      • 1970-01-01
      • 2016-01-31
      • 1970-01-01
      • 2011-07-30
      • 2011-12-30
      • 1970-01-01
      • 1970-01-01
      • 2023-03-24
      相关资源
      最近更新 更多