Groupwise 最大记录查找合同和最新状态

Groupwise maximum record lookup for contracts and latest status

我正在寻求帮助,因为我似乎无法处理 SQL 查询。

我有两个table:

CREATE TABLE `contracts` (
  `id` varchar(5) NOT NULL,
  `partner` varchar(12) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `id` (`id`)
)
CREATE TABLE `locks` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `type` enum('unlock','templock','lock','permalock') DEFAULT NULL,
  `contractID` varchar(5) NOT NULL,
  `partnerID` varchar(12) NOT NULL,
  `stamp` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  `user` varchar(32) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `id` (`id`)
)

我正在尝试获取给定合作伙伴的最新合同状态列表:

SELECT c.id, c.partner ,l.`type`, l.stamp, l.id 
FROM contracts c 
LEFT JOIN locks l
ON c.id = l.contractID 
WHERE partner="2000000301"
GROUP BY c.id ASC

我能够得到结果,但它没有正确指示最后一个状态 - 它“需要”第一个出现:(,而我需要最后一个。

我尝试了顺序方法,即我首先进行查询以检索合约的最后状态:

SELECT max(l.id), l.partnerID ,l.contractID ,l.stamp ,l.`type`  
FROM locks l
WHERE l.partnerID = "2000000301" and l.contractID ="35274";

它工作正常,但如果我尝试将其实现到主查询,使用 'LEFT JOIN(...)'

SELECT *
FROM contracts
LEFT JOIN (
  SELECT max(ll.id), ll.contractID, ll.partnerID, ll.stamp, ll.`type`
  FROM locks ll
  WHERE ll.partnerID = contracts.partner <-- error :(
) l
ON contracts.id = l.contractID 
WHERE partner="2000000301"
ORDER BY contracts.id ASC

'contracts' table 中 'contractID' 字段的可用性存在问题,我得到一个错误 :(

SQL Error [1054] [42S22]: (conn=180) Unknown column 'contracts.partner' in 'where clause'

我已经失去了方法的概念。

我认为它有效:)

SELECT c.id ,c.partner ,l.stamp ,l.`type`
FROM contracts c
LEFT JOIN (
    SELECT l.contractID, l.partnerID, l.stamp, l.`type`
    FROM locks l INNER JOIN (
      SELECT contractID, max(id) as max_id
      FROM locks
      group by contractID
    ) m
    ON l.contractID=m.contractID and l.id=m.max_id  
) l
ON c.id = l.contractID 
WHERE c.partner="2000000301"
ORDER BY c.id ASC

这称为 问题。

您的 locks table 似乎有时会更新,这些更新会更改 stamp 时间戳列。因此,您的问题是为每个 contractID 报告最新的——最近的——locks 记录。从子查询开始以确定每个合约的最新 stamp

                 SELECT MAX(stamp) stamp, contractID
                   FROM locks
                  GROUP BY contractID

然后在您的主查询中使用该子查询来选择 locks 的适当行。

SELECT c.id ,c.partner ,l.stamp ,l.`type`
  FROM contracts c
  LEFT JOIN (
                 SELECT MAX(stamp) stamp, contractID
                   FROM locks
                  GROUP BY contractID
       ) latest ON c.contractID=latest.contractID  
  LEFT JOIN locks l   ON c.contractID = l.contractID
                     AND latest.stamp = l.stamp
 WHERE c.partner="2000000301"
 ORDER BY c.id ASC

请注意,最新的 locks 记录不一定是具有最大 id 值的记录。

当您的锁 table 很大时,该索引将通过启用子查询执行 loose index scan.

来帮助提高查询性能
ALTER TABLE locks ADD INDEX contractid_stamp (contractID, stamp);

而且,您不需要在同一列上同时使用 PRIMARY KEY 和 UNIQUE KEY。 PRIMARY KEY 的作用是保证唯一性。将两个键都放在 table 上会无缘无故地减慢 INSERT。