2

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 番目のものは 2 というようになります。この場合、レコード 4 には 1 のシーケンス番号が必要であり、レコード 5 には 2 の番号が必要であり、レコード 6 には 3 のシーケンス番号が必要です。

送信用のマニフェストをプルするときは、ID で選択するだけです

select * from manifests where id = 5

MySQL で上記のレコードの順序を計算し、それを結果に含めることは可能ですか? 基本的に、必要なのは、対象のレコードよりも前に作成されたが、同じ日に作成されたレコードの数のカウントだと思います。これを実行できる集計関数はありますか、または MySQL でこれを達成するために使用できる他のトリックはありますか?

4

2 に答える 2

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;

パフォーマンスに関しては、このクエリは、メモリ内一時テーブルを内部的に作成するサブクエリ アプローチと比較して、より高速で効率的になります。

上記のクエリをさらに最適化するには、もう 1 つの列closed_date DATEを作成し、このフィールドにインデックスを作成して、この列を結合で使用します。

EXPLAIN EXTENDEX を使用してテーブルで複合インデックスを試すこともできます EXPLAIN を使用したクエリの最適化を参照してください

可能であれば、最高のパフォーマンスを得るために、次のようにテーブルにカバリング インデックスを作成します。

ALTER TABLE manifests ADD KEY ix1(closed_date, id, ... /*all columns used in select*/)
于 2012-07-24T11:40:27.037 に答える
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
于 2012-07-24T11:44:22.063 に答える