尝试根据特定日期*之前*的最新时间戳连接 2 个表

Trying to join 2 tables based on the most recent timestamp *before* a specific date

这是我的 SQL 语句,在我们创建新数据库之前它似乎运行良好。这种方法似乎适用于另一对结构相似的 tables.

SELECT *
FROM tele2_details AS d
    INNER JOIN 
    tele2_usage AS u
    ON    
        d.iccid = u.iccid
    AND
        u.timestamp = (
        SELECT MAX(u.timestamp)
        FROM tele2_usage 
        WHERE u.timestamp <= DATE_FORMAT('2022-01-08 09:30:00','%Y-%m-%d %H:%i:%s') 
      )
WHERE
    accountCustom1='Horizon'

我在这里尝试做的是将详细信息 table 与用法 table 结合起来,用法行仅包含 sim 卡的 iccid、时间戳和它们当前的用法以字节为单位。这应该做的是在指定日期 (2022-01-08 09:30:00) 之前找到最近的使用记录。这应该给我一组模拟人生,每个模拟人生都在指定时间之前加入了它的最新使用记录,但是我通常在这个 tables.

的特定组合上得到零结果

但具体来说,它 确实 匹配日期与查询中指定的日期完全相同的任何记录,但不匹配指定日期之前或等于指定日期的日期。谁能帮我解决我哪里出错了。此查询在以前的数据库中运行良好,我们正在重建我们的系统,现在这已成为一个问题。

在此先感谢您的帮助。


编辑 这里有一些更多的信息,我希望能让这个问题更有意义。所以这里是详细信息的概述 table,我删除了一些列,但这至少是对 table.

的说明
CREATE TABLE `tele2_details` (
    `iccid` VARCHAR(255) NOT NULL,
    `msisdn` VARCHAR(255) NOT NULL,
    `status` VARCHAR(255) NOT NULL,
    `ratePlan` VARCHAR(255) NOT NULL,
    `communicationPlan` VARCHAR(255) NOT NULL,
    PRIMARY KEY (`iccid`)
)
COLLATE='utf8mb4_0900_ai_ci'
ENGINE=InnoDB
;

然后我们还有一个 usages table,它存储 sim 卡的数据使用示例,以及时间戳...

CREATE TABLE `tele2_usage` (
    `id` INT NOT NULL AUTO_INCREMENT,
    `iccid` VARCHAR(255) NOT NULL COLLATE 'latin1_swedish_ci',
    `msisdn` VARCHAR(255) NOT NULL COLLATE 'latin1_swedish_ci',
    `timestamp` DATETIME NOT NULL,
    `ctd_data_usage` BIGINT NOT NULL,
    `ctd_sms_usage` BIGINT NOT NULL,
    `ctd_voice_usage` BIGINT NOT NULL,
    `session_count` INT NOT NULL,
    PRIMARY KEY (`id`)
)
COLLATE='utf8mb4_hr_0900_ai_ci'
ENGINE=InnoDB
AUTO_INCREMENT=10116319
;

我正在尝试创建的查询应该return 一组 sim 详细信息,并与最接近特定时间但不晚于特定时间的使用记录结合在一起。

因此,如果您查看顶部的原始查询,我会尝试将详细信息加入最接近但不是在 2022-01-08 之后的使用记录 09:30:00 * *

我希望这是有道理的。

让我们来看看特定的 sim

SELECT iccid, msisdn, status, ratePlan, communicationPlan FROM tele2_details WHERE iccid='xxxx203605100034xxxx'

1 场比赛结果

"xxxx203605100034xxxx" "xxxx9120012xxxx" "ACTIVATED" "Pay as use - Existing Business" "Data LTE"

如果我查看同一个 sim 的用法 table,我可以看到许多满足我的条件的记录

SELECT id, iccid, TIMESTAMP, ctd_data_usage FROM tele2_usage WHERE iccid='xxxx203605100034xxxx' AND TIMESTAMP <= '2022-01-08 09:30:00'

结果

"10096279"  "xxxx203605100034xxxx"  "2022-01-08 09:01:00"   "77517560"
"10092271"  "xxxx203605100034xxxx"  "2022-01-08 08:01:03"   "77002733"
"10088263"  "xxxx203605100034xxxx"  "2022-01-08 07:01:11"   "76270445"
"10084255"  "xxxx203605100034xxxx"  "2022-01-08 06:01:05"   "76270445"

其中我想 select 第一条记录(带有 09:01 时间戳)以加入详细记录。我可以通过以下查询获得该时间戳

SELECT MAX(timestamp)
FROM tele2_usage 
WHERE TIMESTAMP <= DATE_FORMAT('2022-01-08 09:30:00','%Y-%m-%d %H:%i:%s') AND iccid='xxxx203605100034xxxx'

结果为“2022-01-08 09:01:00”,这正是我想要的。所以现在我把它们放在一起...

SELECT *
FROM tele2_details AS d
    INNER JOIN 
    tele2_usage AS u
    ON    
      d.iccid = u.iccid
    AND
      u.timestamp = (
        SELECT MAX(timestamp)
        FROM tele2_usage 
        WHERE timestamp <= DATE_FORMAT('2022-01-08 09:30:00','%Y-%m-%d %H:%i:%s') 
      )
WHERE
    accountCustom1='Horizon' AND iccid='xxxx203605100034xxxx'

我什么也没得到!我希望取回与该特定 sim 连接的详细记录,但实际上我得到的结果为零,我不明白为什么。

理想情况下,我会删除 iccid 的最终 AND,并且我希望收到该客户的所有模拟人生的集合,使用时间从最接近但不在指定日期之后。

所以有了这个解释,有人知道为什么我没有收到任何记录吗?我有一个类似的 table 用于另一个结构完全相同的 sim 提供商,具有详细信息 table 和用法 table 并且此查询在 table 上工作得很好。我简直无法理解为什么这不起作用。


编辑 2 @Serg 建议尝试为子查询设置别名(我想这就是它的名字),这导致了以下代码...

SELECT *
FROM tele2_details AS d
    INNER JOIN 
    tele2_usage AS u
    ON    
      d.iccid = u.iccid
    AND
      u.timestamp = (
        SELECT MAX(u2.timestamp)
        FROM tele2_usage AS u2
        WHERE u2.timestamp <= DATE_FORMAT('2022-01-08 09:30:00','%Y-%m-%d %H:%i:%s') 
      )
WHERE
    accountCustom1='Horizon'

不幸的是,这仍然导致结果为零。

您应该关联子查询:

SELECT *
FROM tele2_details AS d INNER JOIN tele2_usage AS u
ON d.iccid = u.iccid
AND u.timestamp = (
        SELECT MAX(u2.timestamp)
        FROM tele2_usage u2 
        WHERE d.iccid = u2.iccid AND u2.timestamp <= DATE_FORMAT('2022-01-08 09:30:00','%Y-%m-%d %H:%i:%s') 
      )
WHERE d.accountCustom1='Horizon';

或者,连接到聚合查询:

SELECT *
FROM tele2_details AS d 
INNER JOIN tele2_usage AS u ON d.iccid = u.iccid
INNER JOIN (
  SELECT iccid, MAX(timestamp) timestamp
  FROM tele2_usage 
  WHERE timestamp <= DATE_FORMAT('2022-01-08 09:30:00','%Y-%m-%d %H:%i:%s') 
  GROUP BY iccid
) m ON m.iccid = u.iccid AND m.timestamp = u.timestamp
WHERE d.accountCustom1='Horizon';