はじめに...
私はこの質問に遭遇しました:Difference between 2 adjacent fields - Date - PHP MYSQLと目標を達成しようとしていました。純粋なMySQL。
もう一つの質問(Subtracting one row of data from another in SQL)は、MySQLと似たようなものを作る方法を理解する助けになりました。解決策はまだ固定値または仮定されたデータの順序のいずれかに捨てられているので、問題を解決しませんでしたが、方法論を理解するのに役立ちました。
もう1つの質問()が、次/前の行から値を取得する方法を説明しています。これはまだいくつかの固定値に依存していますが、このテクニックの使い方を学びました。MySQLのdate diffの反復クエリ - 合理化クエリまたは最適化データ構造
- 主キー(
id
)が上昇し、許可される "穴" を命じた:CREATE TABLE `foo` ( `id` int(11) NOT NULL AUTO_INCREMENT, `dateof` date NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
id | dateof -----+------------ 1 | 2012-01-01 2 | 2012-01-02 11 | 2012-01-04 12 | 2012-01-01 13 | 2012-01-02 14 | 2012-01-09 111 | 2012-01-01 112 | 2012-01-01 113 | 2012-01-01
は、2つの前提があります。
は、私は、このテーブルfoo
を持っていると言います。 dateof
の各日付の日付は有効です。意味は「NULL
」で、デフォルト値はありません(0000-00-00
)。 私はすべての行を反復処理し、前のエントリで渡された日数を計算したい、これを受信するために:私は、このソリューションに来た私が学んだすべてで
id | date | days_diff
-----+------------+-----------
1 | 2012-01-01 | 0
2 | 2012-01-02 | 1
11 | 2012-01-04 | 2
12 | 2012-01-01 | -3
13 | 2012-01-02 | 1
14 | 2012-01-09 | 7
111 | 2012-01-01 | -8
112 | 2012-01-01 | 0
113 | 2012-01-01 | 30
(たとえばソリューション1 、別のものがあるので):
SELECT
f.id,
DATE_FORMAT(f.dateof, '%b %e, %Y') AS date,
(SELECT DATEDIFF(f.dateof, f2.dateof)
FROM foo f2
WHERE f2.id = (
SELECT MAX(f3.id) FROM foo f3 WHERE f3.id < f.id
)
) AS days_diff
FROM foo f;
(ここではfiddleはhttp://sqlfiddle.com/#!2/099fc/3)。
これは、魅力的なように機能します。データベースには数個のエントリしか存在しません。多くの場合にはさらに悪化します:
EXPLAIN:
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY f ALL NULL NULL NULL NULL 17221
2 DEPENDENT SUBQUERY f2 eq_ref PRIMARY PRIMARY 4 func 1 Using where
3 DEPENDENT SUBQUERY f3 index PRIMARY PRIMARY 4 NULL 17221 Using where; Using index
18031行:期間:8.672秒。フェッチ:228.515秒
私はdateof
列にインデックスを追加することを考えた:
CREATE TABLE `foo` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`dateof` date DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `dateof` (`dateof`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
...と小さな改善獲得:
EXPLAIN:
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY f index NULL dateof 4 NULL 18369 Using index
2 DEPENDENT SUBQUERY f2 eq_ref PRIMARY PRIMARY 4 func 1 Using where
3 DEPENDENT SUBQUERY f3 index PRIMARY dateof 4 NULL 18369 Using where; Using index
18031行:期間:8.406秒。フェッチ:219.281秒
私は、InnoDBに比べてMyISAMの利点について、どこかで読んでいることを思い出しました。だから私は、MyISAMテーブルに変更:
ALTER TABLE `foo` ENGINE = MyISAM;
18031行:期間:5.671秒。フェッチ:151.610秒
確かにそれは良いが、まだ遅いです。
Iは、別のアルゴリズム(溶液2)と試みた:
SELECT
f.id,
DATE_FORMAT(f.dateof, '%b %e, %Y') AS date,
(SELECT DATEDIFF(f.dateof, f2.dateof)
FROM foo f2
WHERE f2.id < f.id
ORDER BY f2.id DESC
LIMIT 1
) AS days_diff
FROM foo f;
...しかし、それも遅かった:
18031行:持続時間:15.609 秒。フェッチ:184.656秒
このタスクをより速く行っ持つためには、このクエリまたはデータ構造を最適化するための他の方法はありますか?
私はあなたのニーズにより適切なデータ構造が異なるかもしれないと思います。このデータをどのように使用しようとしているか少し詳しくお聞かせください。 – eggyal
@eggyal特に何もありません。私は役に立つかもしれない何かを学ぼうとしているだけです:) – bostaf