【问题标题】:Laravel query - grouping results in a range of datesLaravel 查询 - 在日期范围内对结果进行分组
【发布时间】:2023-01-13 06:18:32
【问题描述】:

我有一张表,我想从中提取满足条件的 object_id 列表:

  • extended_data以“Text1”或“Text2”开头,
  • 对于给定的object_id,表中包含“Text1”和“Text2”的记录之间的时间差小于 2 秒。 我正在发送到目前为止编写的代码和一个包含符合条件的选定记录的示例表。因此,查询应该返回 [3, 7]。 我应该如何扩展代码以获得解决方案?
id object_id extended_data timestamp
1 1 Text1 lorem 12.01.2023 11:01:22
2 2 Text2 lorem 12.01.2023 11:02:25
3 3 Text1 lorem 12.01.2023 11:03:04
4 3 Text2 lorem 12.01.2023 11:03:05
5 4 Lorem 12.01.2023 11:05:44
6 5 Text1 ipsum 12.01.2023 11:05:45
7 null ipsum 12.01.2023 11:06:23
8 6 Text1 ipsum 12.01.2023 11:08:21
9 6 Text2 ipsum 12.01.2023 11:08:32
10 7 Text1 ipsum 12.01.2023 11:09:12
11 7 ipsum 12.01.2023 11:09:12
12 7 Text2 ipsum 12.01.2023 11:09:12
$logs = Logs::whereNotNull('object_id')->get();

$filtered = $logs->filter(function (Logs $log) {
    return str_starts_with($log->extended_data, "Text1") || str_starts_with($log->extended_data, "Text2");
})->values();

foreach ($filtered as $index => $log) {
    $unset = false;
    $actualTimestamp = strtotime($log->timestamp);

    if ($index > 0) {
        $previousTimestamp = strtotime($filtered[$index - 1]->timestamp);
        $differenceInSeconds = $actualTimestamp - $previousTimestamp;
        if ($differenceInSeconds > 2) {
            $unset = true;
        }
    }

    if (count($filtered) - 1 > $index) {
        $nextTimestamp = strtotime($filtered[$index + 1]->timestamp);
        $differenceInSeconds = $nextTimestamp - $actualTimestamp;
        if ($differenceInSeconds > 2) {
            $unset = true;
        }
    }

    if ($unset) {
        $log->unset = true;
    }
}

foreach ($filtered as $index => $log) {
    if (isset($log->unset) && $log->unset) {
        unset($filtered[$index]);
    }
}

【问题讨论】:

    标签: php mysql laravel date eloquent


    【解决方案1】:

    我写这篇文章时假设时间戳列包含有效的日期时间/时间戳 (2023-01-12 11:01:22) 而不是您包含在示例数据中的字符串格式 (12.01.2023 11:01:22)。

    SELECT l1.object_id
    FROM logs l1
    JOIN logs l2
        ON l1.object_id = l2.object_id
        AND l2.extended_data LIKE 'Text2%'
        AND l2.timestamp BETWEEN l1.timestamp AND l1.timestamp + INTERVAL 2 SECOND
    WHERE l1.extended_data LIKE 'Text1%'
    

    而且,假设这个查询的文本是静态的,要运行它你可以这样做 -

    $logs = DB::select("
    SELECT l1.object_id
    FROM logs l1
    JOIN logs l2
        ON l1.object_id = l2.object_id
        AND l2.extended_data LIKE 'Text2%'
        AND l2.timestamp BETWEEN l1.timestamp AND l1.timestamp + INTERVAL 2 SECOND
    WHERE l1.extended_data LIKE 'Text1%'
    ");
    

    使用 Query Builder 构建此查询没有任何好处。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-01-28
      • 2018-07-09
      • 1970-01-01
      • 2016-01-09
      • 2023-01-28
      • 2023-04-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多