0

MySQLにゆっくりと変化するディメンションを処理させたいと考えています。テーブルは「発効日」をコントロールとして使用するように設定されています。したがって、テーブルの構造はhttp://en.wikipedia.org/wiki/Slowly_changing_dimensionTypeII の下部の例に似ています。

この関数を使用して更新/挿入することは可能ですか、それとも関数を分離するのが最善ですか?たとえば、挿入=既存の列を確認してから挿入、更新=元の列を更新、新しい列を挿入

ありがとう

4

2 に答える 2

1

いいえ、できません。このステートメントは、行がすでに存在する場合はその行を更新するため、1つのレコードのみになり、履歴情報が失われます。最初に古いレコードを更新し(end_dateを現在の日付に設定)、次に新しいレコードを挿入する必要があります(end_dateはNULLです)。

于 2012-09-05T11:56:51.460 に答える
0

私は、選択なしで(ただし、挿入/更新を使用して)そのようなアプローチの実装を持っています。MySQL:5.7テーブル構造は次のとおりです。

CREATE TABLE UserStatusLog (
  `user_id` int(11) NOT NULL,
  `status_type` tinyint(8) NOT NULL, // we are logging multiple statuses in one table
  `status_value` int(11) NOT NULL, // actual value of the status
  `is_last` tinyint(1) DEFAULT '1', // marking flag
  `start_ts` timestamp NOT NULL DEFAULT '1970-01-01 00:00:01', // when this status_value became actual
  `finish_ts` timestamp NOT NULL DEFAULT '2030-01-01 00:00:00', // end of actuality for this status
  `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, // just for logging
  `updated` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, // just for logging
  PRIMARY KEY (`user_id`,`status_type`,`finish_ts`),
  UNIQUE KEY `uniq` (`user_id`,`status_type`,`is_last`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

ログに新しい値を挿入しようとしています。

INSERT IGNORE INTO UserStatusLog
(user_id, status_type, status_value, is_last, start_ts, finish_ts)
VALUES ($user_id, $type, $value, NULL, '2017-12-08 15:45:34', '2030-01-01 00:00:00')
ON DUPLICATE KEY UPDATE is_last = IF(start_ts < '2017-12-08 15:45:34' && status_value != VALUES(status_value), 
2 /* THIS IS A "SPECIAL VALUE" for is_last */
, is_last);

次に、mysql_affected_rows()を介してクエリの結果を比較しています。

  • 0start_tsが新しいレコードよりも大きいレコードがあります。
  • 1これはログ内の最初のユーザーのレコードであり、更新を実行する必要があり、このレコードにis_lastをマークします。

    UPDATE UserStatusLog SET is_last = 1 WHERE user_id = $ user_id AND status_type = $ type AND finish_ts = '2030-01-01 00:00:00' LIMIT 1;

  • 2新しいstart_tsよりも古いレコードがあり、is_last = 2(SPECIAL VALUE)で更新しました。

    UPDATE test.mock_20171208_47d9ac21808ee65d605ca32205888648 SET is_last = NULL、finish_ts = '2017-12-08 15:45:45' WHERE user_id = $ user_id AND status_type = $ type AND is_last = 2 LIMIT 1; //新しい、本当に最後のレコードを挿入INSERT INTO test.mock_20171208_47d9ac21808ee65d605ca32205888648(user_id、status_type、status_value、is_last、start_ts、finish_ts)VALUES($ user_id、$ type、$ value、$ is_last = 1、 '2017-12-08 15: 45:45'、' 2030-01-01 00:00:00');

于 2017-12-08T16:00:43.690 に答える