web-dev-qa-db-ja.com

列比較のMySQLインデックス

WHERE col1 > col2のような列の比較に使用するインデックスを設定するにはどうすればよいですか?

col1およびcol2はDATETIMEタイプです。

5
Dude

テーブルのレイアウトが次のようであるとします。

CREATE TABLE mytable
(
    id int not null auto_increment,
    col1 datetime,
    col2 datetime,
    primary key (id)
);

あなたは2つのことの1つを試してみたいかもしれません

アイデア#1:差を秒単位で保存する列を作成する

列を作成し、次のように入力します

ALTER TABLE mytable ADD COLUMN dtdiff INT NOT NULL;
ALTER TABLE mytable ADD INDEX (dtdiff);
UPDATE mytable SET dtdiff = UNIX_TIMESTAMP(col1) - UNIX_TIMESTAMP(col2)l

テーブルに外部キーまたは制約がない場合は、代わりに次のようにします。

CREATE TABLE mytable_new LIKE mytable;
ALTER TABLE mytable_new ADD COLUMN dtdiff INT NOT NULL;
ALTER TABLE mytable_new ADD INDEX (dtdiff);
INSERT INTO mytable_new
    SELECT id,col1,col2,
    UNIX_TIMESTAMP(col1) - UNIX_TIMESTAMP(col2)
    FROM mytable
;
ALTER TABLE mytable RENAME mytable_old;
ALTER TABLE mytable_new RENAME mytable;
DROP TABLE mytable_old;

完了すると、クエリは基本的に

  • SELECT * FROM mytable WHERE dtdiff > 0 ために col1 > col2
  • SELECT * FROM mytable WHERE dtdiff < 0 ために col1 < col2

アイデア#2:差を秒単位で保存する別のテーブルを作成する

CREATE TABLE mytable_dtdiff
(
    id int not null,
    dtdiff int not null,
    primary key (id),
    key dtdiff (dtdiff)
);
INSERT INTO mytable_dtdiff
SELECT id,UNIX_TIMESTAMP(col1) - UNIX_TIMESTAMP(col2)
FROM mytable;

完了すると、クエリは基本的に

SELECT B.* FROM
(SELECT id FROM mytable_dtdiff WHERE dtdiff > 0) A
LEFT JOIN mytable B USING (id);

ために col1 > col2および

SELECT B.* FROM
(SELECT id FROM mytable_dtdiff WHERE dtdiff < 0) A
LEFT JOIN mytable B USING (id);

ために col1 < col2

試してみる !!!

1
RolandoMySQLDBA

MySQLでこれを行う簡単な方法はありません。

回避策の1つは、比較の値を別の列に格納することです。たとえば、cmpとし、それにインデックスを付けて、WHERE col1> col2の代わりに使用します。

Col1 <col2の場合は-1、col1 = col2の場合は0、col1> col2の場合は1を格納できます。このようにして、<、<=、=、> =、>、<>の比較の結果を簡単に取得できます。

Cmp値をcol1およびcol2の値と同期させる最も簡単な方法は、col1またはcol2の値が更新されるたびにアプリケーションコードでそれを更新することです。

データが複数のアプリケーションから更新された場合、またはアプリに更新ロジックを配置したくない場合は、UPDATEおよびINSERTトリガーを使用して、cmpの値を計算および更新できます。

0
redguy