获得有序结果集中行的常量

时间:2012-07-24 11:26:03

标签: mysql aggregate-functions ordinal

我有一组存储在MySQL数据库中的清单记录。架构如下:

CREATE TABLE `manifests` (
    `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    `carrier_id` INT(10) UNSIGNED NOT NULL COMMENT 'The carrier for which this manifest is being made',
    `opened` DATETIME NOT NULL COMMENT 'Time the manifest was created',
    `closed` DATETIME NULL DEFAULT NULL COMMENT 'Time the manifest was picked up and closed',
    PRIMARY KEY (`id`),
    INDEX `manifests_to_carriers_id` (`carrier_id`),
    CONSTRAINT `manifests_to_carriers_id` FOREIGN KEY (`carrier_id`) REFERENCES `carriers` (`id`)
)
COMMENT='List of manifests that have been created by the system'
COLLATE='utf8_general_ci'
ENGINE=InnoDB;

白天可能会有几个清单关闭和发送。我可以按照发送的顺序轻松获取特定日期的所有清单。例如,我可以获得今天发送的所有清单。

select * 
from manifests 
where date(closed) = date(now())
order by closed

这将生成如下数据:

"id"  "carrier_id"  "opened"               "closed"
"4"   "1"           "2012-07-24 11:10:06"  "2012-07-24 11:10:32"
"5"   "1"           "2012-07-24 11:10:40"  "2012-07-24 11:11:08"
"6"   "1"           "2012-07-24 11:11:17"  "2012-07-24 11:11:59"

运营商需要一个序列号也包含在我们发送的数据中。在特定日期发送的第一个应该是1,第二个应该是2,依此类推。在这种情况下,记录4需要序列号1,记录5需要2的数量,记录6需要序列号3,依此类推。

当我拉动清单进行传输时,我只需按ID

选择它
select * from manifests where id = 5

是否有可能让MySQL计算上述记录的正常性并将其包含在结果中?基本上我认为我需要的是在感兴趣的记录之前创建的记录数量的计数,但也是在同一天创建的。是否有可以执行此操作的聚合函数,或者是否可以使用其他一些技巧来实现MySQL?

2 个答案:

答案 0 :(得分:4)

SET @var_record = 0;

SELECT *, (@var_record := @var_record + 1) AS ordinality
FROM manifests 
WHERE DATE(closed) = DATE(NOW())
ORDER BY closed;

这就是你要找的东西吗?

编辑:新查询:

SELECT a.*, SUM(IF(b.id IS NOT NULL, 1, 0)) AS ordinality
FROM   manifests a
       LEFT JOIN manifests b
           ON (DATE(a.closed) = DATE(b.closed) AND a.closed > b.closed)
GROUP BY a.id;

性能方面,与在内部创建内存临时表的子查询方法相比,此查询将更快,更高效。

要进一步优化上述查询,您可以再创建一列closed_date DATE并在此字段上创建索引,并在连接中使用此列。

您还可以使用EXPLAIN EXTENDEX在表格上尝试复合索引,请参阅Optimizing Queries with EXPLAIN

如果可能的话,然后在桌面上创建一个覆盖索引,以获得最佳性能:

ALTER TABLE manifests ADD KEY ix1(closed_date, id, ... /*all columns used in select*/)

答案 1 :(得分:1)

我确实提出了一些有效的方法,但我认为它不是最优的,所以如果有更好的方法我还在寻找它。

SELECT *, (
    SELECT COUNT(closed) 
    FROM manifests AS b 
    WHERE DATE(b.closed) = DATE(a.closed) 
    AND b.closed <= a.closed) AS ordinality
FROM manifests AS a
WHERE a.id=5