4

我有一个外部 3rd 方程序将数据库实时导出到 mysql,我想显示用于报告的数据。所以,我不能改变结构,因为它是实时同步的。

表结构是这样的

ID | Date       | Transaction
-----------------------------
12 | 2012-11-01 | 200
12 | 2012-11-02 | 250
12 | 2012-11-03 | 150
12 | 2012-11-04 | 1000
12 | 2012-11-05 | 225
....
13 | 2012-11-01 | 175
13 | 2012-11-02 | 20
13 | 2012-11-03 | 50
13 | 2012-11-04 | 100
13 | 2012-11-05 | 180
13 | 2012-11-06 | 195

数据非常大,而且每天都在变大。

我想做的是基于以下内容构建报告(视图表):

ID | Date       | Transaction | Prev Day Transaction
----------------------------------------------------
12 | 2012-11-01 | 200         | 0
12 | 2012-11-02 | 250         | 200
12 | 2012-11-03 | 150         | 250
12 | 2012-11-04 | 1000        | 150
12 | 2012-11-05 | 225         | 1000
....
13 | 2012-11-01 | 175         | 0
13 | 2012-11-02 | 20          | 175
13 | 2012-11-03 | 50          | 20
13 | 2012-11-04 | 100         | 50
13 | 2012-11-05 | 180         | 100
13 | 2012-11-06 | 195         | 180

我只是无法获得快速选择语句。目前原始数据已经是 283,120 行。它将每天增长 500 行。

我试过类似的东西:

SELECT *, (SELECT transaction FROM table as t2 WHERE t1.id=t2.id 
AND t1.date>t2.date ORDER BY t2.date DESC LIMIT 0,1)
FROM table AS t1

它正在工作,但 select 语句非常慢。大多数时候,它会在手术过程中被切断。

我需要帮助的是一个非常快速的 sql 语句,稍后我可以使用它来构建视图表。

4

4 回答 4

3

看到这个链接:http ://sqlfiddle.com/#!2/54a5e/12

select t.id,t.cDate,t.cTrans
  ,(case when @pID=t.id then @pTran else 0 end) as preT 
  ,(@pID :=t.id) as `tID`,(@pTran := t.cTrans) as `tTrans` 
from tb_test_1 as t,(select @pID = 0, @pTran = 0) as t2
order by id,cDate;

tIDtTrans列必须保留,不能在页面上显示。

请原谅我,因为我只会一点英语!

于 2012-11-27T03:12:18.020 回答
2

试试这个查询 -

SELECT t1.*, COALESCE(t2.transaction, 0) Prev_Day_Transaction FROM trans t1
  LEFT JOIN (SELECT * FROM trans ORDER BY id, date DESC) t2
    ON t1.id = t2.id AND t1.date > t2.date
GROUP BY t1.id, t1.date;

+------+------------+-------------+----------------------+
| id   | date       | transaction | Prev_Day_Transaction |
+------+------------+-------------+----------------------+
|   12 | 2012-11-01 |         200 |                    0 |
|   12 | 2012-11-02 |         250 |                  200 |
|   12 | 2012-11-03 |         150 |                  250 |
|   12 | 2012-11-04 |        1000 |                  150 |
|   12 | 2012-11-05 |         225 |                 1000 |
|   13 | 2012-11-01 |         175 |                    0 |
|   13 | 2012-11-02 |          20 |                  175 |
|   13 | 2012-11-03 |          50 |                   20 |
|   13 | 2012-11-04 |         100 |                   50 |
|   13 | 2012-11-05 |         180 |                  100 |
|   13 | 2012-11-06 |         195 |                  180 |
+------+------------+-------------+----------------------+

将复合索引 (id, date) 添加到表中。

============================

ALTER TABLE mt4_daily
  ADD INDEX IX_mt4_daily_DATE (DATE);

ALTER TABLE mt4_daily
  ADD INDEX IX_mt4_daily (ID, DATE);
于 2012-11-26T07:40:38.583 回答
1

通过 select 语句将表分成几个部分,并使用 UNION Set 运算符将它们连接起来。由于所有集合运算符都是并行操作,因此您将非常快速地获取数据。您可以使用表中的唯一数字列来划分数据。例如

select * from tbl_x where col1%3=0 union
select * from tbl_x where col1%3=1 union
select * from tbl_x where col1%3=2 ...

上面的sql查询分数据并行取数据

于 2012-11-26T07:30:00.727 回答
1

我会尝试这样编写查询:

SELECT
  tbl.ID,
  tbl.Date,
  tbl.Transaction,
  COALESCE(tbl1.Transaction,0) as PrevDay
FROM
  tbl left join tbl tbl1
  on tbl.ID = tbl1.ID
     and tbl.Date = tbl1.Date + INTERVAL 1 DAY

(这只有在您确保表格包含所有日期时才有效,如果您错过了一天,第二天将始终显示 PrevDay 为 0,我不确定这是否是您需要的)。

编辑:即使缺少某些日子,我也会尝试这种可行的解决方案:

SELECT
  tbl.id,
  tbl.date,
  tbl.Transaction,
  COALESCE(tbl1.Transaction,0) as PrevDay
FROM
  (SELECT tbl.id, tbl.date as d1, max(tbl1.ddate) as d2
   FROM tbl LEFT JOIN tbl tbl1
        ON tbl.id = tbl1.id and tbl.date>tbl1.date
   GROUP BY tbl.id, tbl.date) t
  LEFT JOIN tbl on tbl.id = t.id and DATE(tbl.ddate) = DATE(t.d1)
  LEFT JOIN tbl tbl1 ON tbl1.id = t.id and DATE(tbl1.date) = DATE(t.d2)
于 2012-11-26T07:41:17.523 回答