php 我怎样才能查询日期之间的2列相同的用户名在MySQL中

8zzbczxx  于 2023-01-01  发布在  PHP
关注(0)|答案(2)|浏览(116)

我有一个mysql表,其中有“用户名”,“acctstarttime”和“acctstoptime”(和一个“id”)日期时间列。我需要获取具有相同用户名的其他“acctstarttime”和“acctstoptime”记录之间的acctstarttime或acctstoptime记录。例如,“John”有3条记录。
| 身份证|用户名|帐户开始时间|实际停止时间|
| - ------|- ------|- ------|- ------|
| 1个|约翰|二○二二年十二月二十九日|二○二三年一月一日|
| 第二章|约翰|二○二二年十二月三十日|二○二三年三月三日|
| 三个|约翰|二○二二年十二月十二日|二○二二年十二月十四日|
第二行acctstarttime在第一行acctstarttime和acctstoptime之间,第一行acctstoptime在第二行acctstarttime和acctstoptime之间。我想查询这2条记录。
我可以用php做,但是100万条记录大约需要3-4天或者更多。我的功能非常低效。
在mysql或php中我怎样才能减少这个时间(只是加速)?
我根据用户名将每个记录下载到不同的文件中。我写了这个laravel代码,但是它工作得太慢了。它可能会让人困惑。

function findRecordsBetweenSameHours()
    {
        $directory = storage_path() . "/app/";
        $files = Storage::files('usernames');
        foreach ($files as $file) {
            $records =json_decode(file_get_contents($directory . $file), true);
            foreach ($records as $record) {
                $record["acctstarttime"] = Carbon::createFromFormat('Y-m-d H:i:s', $record["acctstarttime"]);
                $record["acctstoptime"] = Carbon::createFromFormat('Y-m-d H:i:s', $record["acctstoptime"]);
                foreach ($records as $record2) {
                    $record2["acctstarttime"] = Carbon::createFromFormat('Y-m-d H:i:s', $record2["acctstarttime"]);
                    $record2["acctstoptime"] = Carbon::createFromFormat('Y-m-d H:i:s', $record2["acctstoptime"]);
                    if (
                        ($record2["acctstoptime"]->between($record["acctstarttime"], $record["acctstoptime"], false)
                            || $record2["acctstarttime"]->between($record["acctstarttime"], $record["acctstoptime"], false)
                        )
                        && $record2["acctsessionid"] != $record["acctsessionid"]
                ) {
                        Storage::append('x.log',
                            $record["acctsessionid"] . " - " . $record2["acctsessionid"] . " - " . $record["username"]
                        );

                    }
                }
            }
        }
        Storage::append('x.log',
            "finish"
        );
    }
yc0p9oo0

yc0p9oo01#

您可以这样编写查询

SELECT 
    t1.*
FROM
    table_name t1
        JOIN
    table_name t2 ON t1.username = t2.username
WHERE
    (t1.acctstarttime > t2.acctstarttime
        AND t1.acctstarttime < t2.acctstoptime)
        OR (t1.acctstoptime > t2.acctstarttime
        AND t1.acctstoptime < t2.acctstoptime);
du7egjpx

du7egjpx2#

根据我对您问题的理解,您希望存在具有相同用户名和重叠时间段的另一个记录。
我推荐exists和一些不等式条件:

select *
from mytable t1
where exists (
    select 1
    from mytable t2
    where t1.id != t.id
      and t1.username = t2.username
      and t1.acctstarttime <= t2.acctstoptime 
      and t2.acctstarttime <= t1.acctstoptime
)

对于每一行,子查询搜索同一用户的“重叠”记录,并筛选匹配的行。开始时间和结束时间的不等条件限定日期范围重叠。
(id, acctstarttime, acctstoptime)上的索引可能有助于提高性能。

相关问题