Scott mang đến một điểm tuyệt vời về những ngày thị trường liên tiếp. Tôi khuyên bạn nên xử lý này với một bảng kết nối như:
CREATE TABLE `market_days` (
`market_day` MEDIUMINT(8) UNSIGNED NOT NULL AUTO_INCREMENT,
`date` DATE NOT NULL DEFAULT '0000-00-00',
PRIMARY KEY USING BTREE (`market_day`),
UNIQUE KEY USING BTREE (`date`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=0
;
Khi ngày càng nhiều ngày trôi qua trên thị trường, chỉ INSERT
date
giá trị mới trong bảng. market_day
sẽ tăng tương ứng.
Khi chèn prices
dữ liệu, tra cứu LAST_INSERT_ID()
hoặc giá trị tương ứng với một giá trị đã cho trước đây cho date
.
Đối với prices
bảng riêng của mình, bạn có thể thực hiện lưu trữ, SELECT
và INSERT
hoạt động hiệu quả hơn với một PRIMARY KEY
hữu ích và không AUTO_INCREMENT
cột. Trong lược đồ bên dưới, PRIMARY KEY
của bạn chứa thông tin hữu ích thực chất và không chỉ là một quy ước để xác định các hàng duy nhất. Sử dụng MEDIUMINT
(3 byte) thay vì INT
(4 byte) tiết kiệm thêm một byte cho mỗi hàng và quan trọng hơn 2 byte cho mỗi hàng trong PRIMARY KEY
- tất cả trong khi vẫn affording hơn 16 triệu ngày có thể và biểu tượng ticker (mỗi).
CREATE TABLE `prices` (
`market_day` MEDIUMINT(8) UNSIGNED NOT NULL DEFAULT '0',
`ticker_id` MEDIUMINT(8) UNSIGNED NOT NULL DEFAULT '0',
`price` decimal (7,2) NOT NULL DEFAULT '00000.00',
PRIMARY KEY USING BTREE (`market_day`,`ticker_id`),
KEY `ticker_id` USING BTREE (`ticker_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
;
Trong sơ đồ này mỗi hàng là duy nhất trên mỗi cặp market_day
và ticker_id
. Dưới đây ticker_id
tương ứng với một danh sách các biểu tượng ticker trong một bảng tickers
với một sơ đồ tương tự như market_days
bảng:
CREATE TABLE `tickers` (
`ticker_id` MEDIUMINT(8) UNSIGNED NOT NULL AUTO_INCREMENT,
`ticker_symbol` VARCHAR(5),
`company_name` VARCHAR(50),
/* etc */
PRIMARY KEY USING BTREE (`ticker_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=0
;
Điều này mang lại một truy vấn tương tự như những người khác đề xuất, nhưng với hai sự khác biệt quan trọng: 1) Không có sự biến đổi chức năng vào cột ngày, phá hủy khả năng của MySQL để sử dụng các khóa trên tham gia; trong truy vấn bên dưới MySQL sẽ sử dụng một phần của số PRIMARY KEY
để tham gia trên market_day
. 2) MySQL chỉ có thể sử dụng một khóa cho mỗi mệnh đề JOIN
hoặc WHERE
. Trong truy vấn này, MySQL sẽ sử dụng chiều rộng đầy đủ của PRIMARY KEY
(market_day
và ticker_id
) trong khi trong truy vấn trước nó chỉ có thể sử dụng một (MySQL thường sẽ chọn lọc nhiều hơn hai).
SELECT
`market_days`.`date`,
`tickers`.`ticker_symbol`,
`yesterday`.`price` AS `close_yesterday`,
`today`.`price` AS `close_today`,
(`today`.`price` - `yesterday`.`price`)/(`yesterday`.`price`) AS `pct_change`
FROM
`prices` AS `today`
LEFT JOIN
`prices` AS `yesterday`
ON /* uses PRIMARY KEY */
`yesterday`.`market_day` = `today`.`market_day` - 1 /* this will join NULL for `today`.`market_day` = 0 */
AND
`yesterday`.`ticker_id` = `today`.`ticker_id`
INNER JOIN
`market_days` /* uses first 3 bytes of PRIMARY KEY */
ON
`market_days`.`market_day` = `today`.`market_day`
INNER JOIN
`tickers` /* uses KEY (`ticker_id`) */
ON
`tickers`.`ticker_id` = `today`.`ticker_id`
WHERE
`today`.`price` > 0
AND
`yesterday`.`price` > 0
;
Một điểm tốt hơn là sự cần thiết cũng tham gia chống lại tickers
và market_days
để hiển thị thực tế ticker_symbol
và date
, nhưng các hoạt động này là rất nhanh kể từ khi họ sử dụng các phím.
@Scott: Cảm ơn bạn đã bình luận. Tôi có thể thay đổi dấu thời gian chỉ là ngày để làm cho mọi thứ dễ dàng hơn là phải đối phó với các phạm vi. –
@Knix Chức năng ngày khá sạch sẽ, không chắc chắn nó đắt tiền như thế nào, nhưng chắc chắn là cuộc gọi của bạn. Vẫn còn một vấn đề về thị trường đóng cửa vào cuối tuần và ngày lễ. trướcĐóng cột loại bỏ sự tự tham gia, sự lộn xộn của những ngày thị trường đóng cửa với chi phí sao chép dữ liệu và phải biết trước khi đóng ngày hôm nay. – Scott
Cảm ơn ... Tôi sẽ đưa ra lời khuyên của bạn! –