インポートされたデータを使用して欠落しているシーケンスのリストを提供するレポートに取り組んでいます。
CREATE TABLE `client_trans`
(
`id` INT NOT NULL AUTO_INCREMENT,
`client_id` INT NULL,
`sequence` INT NULL,
`other_data` INT NULL,
PRIMARY KEY (`id`),
INDEX `client_id_seq` (`client_id` ASC, `sequence` ASC)
);
id フィールドを除いて、真に一意の値や値の組み合わせは存在しません
このテーブルのデータは次のようになります (other_data フィールドは無視します)。
id client_id sequence
1 1000 1
2 1000 2
3 1000 2
4 1000 3
5 1001 1
6 1001 5
7 1001 6
8 1002 4
9 1002 6
上記の例のように、複数の client_id/sequence の組み合わせが可能であり、シーケンスが 1 (または 0) で開始されない可能性があります。
この質問への回答のバリエーションなど、欠落しているシーケンスを見つけるためのクエリを実行することは可能ですが、これには非常に時間がかかる可能性があります
この方法に代わる方法は、(Pentaho データ統合ツールを使用して) データがテーブルに挿入される前またはその間にいくつかの挿入/更新クエリを実行し、欠落している client_id/sequence 値を含む追加のテーブルを使用することでした。これは、上記の例で (client_id, sequence) の値 (1001, 5) を挿入すると、次のクエリのようなものを使用して、シーケンス 2 ~ 4 が欠落していることが検出されることを意味します。
CREATE TABLE `missing_sequences` (
`client_id` int(11),
`miss_start` int(11),
`miss_end` int(11),
)
(Pentaho Execute SQL ステートメントの代わりに SQL でクエリをテストしやすくするために、挿入はコメントアウトされているため、単なる選択であることに注意してください)
SET @temp_id = 1001;
SET @temp_seq = 5;
/* Replace temp_id, temp_seq references with ? in Pentaho */
/* INSERT INTO missing_sequences (id, miss_start, miss_end) */
SELECT @temp_id id, max(t1.seq) + 1 missing_start, @temp_seq - 1 missing_end
FROM client_trans t1
CROSS JOIN client_trans t2
WHERE t1.id = @temp_id
AND t1.seq < @temp_seq
AND t2.id = @temp_id
AND t2.seq >= @temp_seq - 1
HAVING missing_end >= missing_start
結果:
id missing_start missing_end
1001 2 4
これにより、欠落しているシーケンス テーブルがある程度正常に読み込まれますが、以前に欠落していたシーケンスの 1 つを含む行が追加されると、問題が発生します。
(当初、client_id と miss_start に基づくプライマリ インデックスもありました。これにより、追加された重複値も処理されますが、これが正しいかどうかは完全にはわかりませんでした)
挿入されたシーケンス番号に応じて、次の 4 つの可能性のいずれかが存在します。例を次に示します。
@temp_seq = missing_start : (@temp_seq = 2)
update missing_start += 1
missing_start < @temp_seq < missing_end : (@temp_seq = 3)
split into two records
@temp_seq = missing_end : (@temp_seq = 4)
update missing_end -= 1
@temp_seq = missing_start = missing_end : (@temp_id = 1002, @temp_seq = 5)
delete record from missing_sequences table
これが私の問題の出番です (インポートされたデータがソートされない可能性があることを考慮した場合):
Pentaho データ統合変換での最初の挿入と複製だけでなく、各可能性にどのように対応すればよいでしょうか?
編集: ブレーンストーミングの後、MySQL で実行すると機能するように見える次のスクリプトを思いつきましたが、「SQL ステートメントの実行」トリガーとして実行すると機能しません。これは、(client_id, missing_start) の missing_sequences テーブルのプライマリ インデックスです。
SET @orig_start = 0;
SET @orig_end = 0;
SET @temp_client_id = ?;
SET @temp_sequence = ?;
/* Find closest matching record and save start/end values*/
SELECT client_id, @orig_start:=miss_start miss_start, @orig_end:=miss_end miss_end
FROM missing_sequences
WHERE client_id = @temp_client_id
AND miss_start <= @temp_sequence
AND miss_end >= @temp_sequence
LIMIT 1; /* Just in case, delete all matches later anyway */
/* Delete the above record if exists */
DELETE FROM missing_sequences
WHERE client_id = @temp_client_id AND miss_start = @orig_start AND miss_end = @orig_end;
/* Insert new value. This will insert the FIRST value in the table
eg. if 1-10 is missing and 5 inserted, this will insert 1-4 as missing */
INSERT INTO missing_sequences (client_id, miss_start, miss_end)
SELECT @temp_client_id client_id, @curr_start := max(t1.sequence) + 1 miss_start, @curr_end := @temp_sequence - 1 miss_end
FROM client_trans t1
CROSS JOIN client_trans t2
WHERE t1.client_id = @temp_client_id
AND t1.sequence < @temp_sequence
AND t2.client_id = @temp_client_id
AND t2.sequence >= @temp_sequence - 1
HAVING miss_end >= miss_start
ON DUPLICATE KEY UPDATE client_id = @temp_client_id,miss_start = @curr_start;
/* Insert upper missing value if it is different */
INSERT INTO missing_sequences (client_id, miss_start, miss_end)
SELECT @temp_client_id client_id, @curr_end + 2 missing_start, @orig_end missing_end
FROM dual
WHERE @curr_end + 2 <= @orig_end
ON DUPLICATE KEY UPDATE client_id = @temp_client_id,miss_start = @curr_start;
行ごとに実行と変数置換ボックスがチェックされていますが、実行に一貫性がないか、欠落しているシーケンステーブルがまったく更新されていないようです