|
只要我的表一直在增长,自从我实施了向我推荐的代码,sql查询需要越来越长的时间。一开始需要1000秒才能执行8秒。现在在有2.5万多行的表上,只是失败了。
& y$ K* V+ ^3 T1 e5 p) `, h**您可以在这里观看我的查询-http://sqlfiddle.com/#!2/5c480/1/0**
0 g( O" ^8 X z# u" cSELECT a.ID,DATE_FORMAT(a.Time,'%d/%m/%y') AS T,a.SerialNumber,p.Model, b.Remain_Toner_Black BeforeCountBlack, a.Remain_Toner_Black AfterCountBlack, b.Remain_Toner_Cyan BeforeCountCyan, a.Remain_Toner_Cyan AfterCountCyan,b.Remain_Toner_Magenta BeforeCountMagenta, a.Remain_Toner_Magenta AfterCountMagenta,b.Remain_Toner_Yellow BeforeCountYellow, a.Remain_Toner_Yellow AfterCountYellowFROM SELECT a.ID, a.Time, a.SerialNumber, a.Remain_Toner_Black, a.Remain_Toner_Cyan, a.Remain_Toner_Magenta, a.Remain_Toner_Yellow, SELECT COUNT(*) FROM Reports c WHERE c.SerialNumber = a.SerialNumber AND c.ID = 0) OR (b.Remain_Toner_Cyan = 0) OR (b.Remain_Toner_Magenta = 0) OR (b.Remain_Toner_Yellow = 0)我需要处理以下三个表,以便只选择它们ID特定公司的打印机。8 p. @% ?. z x
报告:
, y: R: n3 M- v$ g! m$ m- S# oID SerialNumber Remain_Toner_Black 29881 Z30PBAHBB00034E 58 30001 58 58 Z30PBAHBB00034E Z30PBAHBB00034E BVCfdgdfgdf329F5030207 5030303030202070707 BVCfdgdfgdf329F Z30PBAHBB00034E5030301 5030303030303030303010101 Z30PBAHBB00034E 100打印机:/ t! Q6 ]" j H% D F, X- Z
IP SerialNumber Customer 80.179.228.81 Z30PBAHBB00034E 52顾客:
+ @, P1 ?, N+ J5 e3 u7 C& nID IP Company 52 808080800 52 .179.228.81 5我的查询工作很完美,回来了:
* I3 F% ^% w' yID SerialNumber BEFORECOUNTBLACK AFTERCOUNTBLACK 30001 300010001 Z30PBAHBB00034E 58 Z30PBAHBB00034E 50 50000 但同样,现在我在表中有2.5万行Reports它在表面运行时会失败。
9 }7 u/ a6 X- H) i
5 h' A: b* i& r 解决方案:
4 o0 C( y3 y) d 这是你的问题1的解决方案,它会运行得更快,因为你有很多全表扫描和相关子查询。在这里,您最多只扫描一次表(可能还有一个临时表,这取决于您的数据量和内存)。我认为你可以在这里轻松调整,以适应你的问题。问题2(我还没有真正读过)也可能得到回答,因为现在很容易添加wheredate_column = whatever! t# ^" B$ I& K; F! E, m Q
select * from select t.*, if(@prev_toner </u>编辑:
; V3 h0 e+ t& s; L2 L3 ^解释:
* l: p8 a4 T1 G+ C( t用这条线
. {5 t0 @/ C: Z1 ?/ p ,(select @prev_toner:=0,@prev_sn:=SerialNumber from Table1 order by SerialNumber我们只是初始变量@prev_toner,并@prev_sn在操作中。相当于这次旅行根本不包含在查询中,而是在查询前编写
. T( \' f" [0 oSET @prev_toner = 0;SET @prev_sn = (select serialnumber from your_table order by serialnumber limit 1);SELECT ...那为什么要查询呢?@prev_sn分配一个值,为什么要按序列号排序?顺序非常重要。如果没有顺序,返回行的顺序就无法保证。同样,我们将使用变量访问前一行的值,因此分组相同的序列号非常重要。) p! y: `/ M+ Z/ I6 I$ d. G; y
select句子中的列是一个接一个地求值的,所以首先选择这次旅行是非常重要的/ n6 z9 f6 }, p: v& [( c9 _ b. j) g
if(@prev_toner 在选择这两行之前+ K7 \* q4 j3 a/ B- a
@prev_sn := SerialNumber,@prev_toner := Remain_Toner_Black为什么?最后两行只将当前行的值分配给变量。为此,在这一行; T4 g9 l0 m1 N" v
if(@prev_toner 变量仍然保留前几行的值。我们在这里所做的无非是说:如果Remain_Toner_Black列中的前一行值小于当前行中的值 ,! @3 ?, u0 ^6 ]; z9 v+ i& a
而且前几行的序列号与实际行的序列号相同,则返回1,否则返回0 。
* n/ ~ L& u3 X4 {/ J2 H然后,我们可以在外部查询中简单地说选择每一行,其中上述返回1。
2 e( F1 l8 o* e根据你的查询,你不需要所有这些子查询。它们非常昂贵和不必要。事实上,这是疯狂的。查询的这部分* G! D: M: t3 y* r. z r
SELECT a.ID, a.Time, a.SerialNumber, a.Remain_Toner_Black, a.Remain_Toner_Cyan, a.Remain_Toner_Magenta, a.Remain_Toner_Yellow, SELECT COUNT(*) FROM Reports c WHERE c.SerialNumber = a.SerialNumber AND c.ID 您选择 整个表格, 并 为每一行" W9 b4 D" O& ?4 Q' z: a
计算组中的行。这是一个依赖的子查询。所有这些都只是为了拥有一定的行号。然后再次进行此操作,以便您连接这两个临时表以获得最后一行。真的,难怪性能太差了。
0 M$ q: \$ E6 z$ _那么,如何根据您的查询调整我的解决方案呢?我没有用它来获取Remain_Toner_Black前一行的一个变量是黑色、蓝色、红色和黄色。就像你一样,只要添加一个打印机和客户表。别忘了订购的顺序,你已经完成了。 |
|