通過介紹的方式...
我遇到了這個問題:Difference between 2 adjacent fields - Date - PHP MYSQL,並試圖實現目標,即迭代通過日期和得到差異,與純粹的MySQL。
那裏的另一個問題(Subtracting one row of data from another in SQL)幫助我瞭解如何使MySQL與類似的東西。它並沒有解決問題,因爲解決方案仍然是固定值或假定的數據順序,但它確實有助於我理解方法。
還有一個問題(How to get next/previous record in MySQL?),其答案描述瞭如何從下一個/上一個行獲取值。它仍然依賴於一些固定值,但我學會了如何使用這種技術。MySQL日期差異迭代查詢 - 簡化查詢或優化數據結構
說我有這個表foo
:
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
有兩個假設:
- 主鍵(
id
)有序上升,並允許 「洞」。 dateof
中的每一個日期列均有效,意思是:沒有NULL
s,沒有默認值(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;
(示例小提琴在這裏: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秒。
我記得在某些情況下讀了一些關於MyISAM優於InnoDB的地方。所以我改變了在MyISAM:
ALTER TABLE `foo` ENGINE = MyISAM;
18031行:時間:5.671秒。取指:151.610秒。
確定它更好但仍然很慢。
我試圖與另一算法(溶液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 2012-04-25 18:03:07
@eggyal沒什麼特別的。我只是想學習一些可能有用的東西:) – bostaf 2012-04-25 18:30:00