2015-06-08 121 views
0

我遇到了SQL查詢的問題。當值更改時選擇sql行

我正在使用MariaDB。我有一個包含多個字段的表,我希望在更改值時選擇行。

例如:

+------------+----------+----------+ 
| time_stamp | G1.state | G2.state | 
+------------+----------+----------+ 
| 1433717821 | 3  | 1  | 
+------------+----------+----------+ 
| 1433717881 | 3  | 1  | 
+------------+----------+----------+ 
| 1433717942 | 5  | 1  | 
+------------+----------+----------+ 

在這裏,我需要得到3個時變爲5.我已經試過以下查詢TIME-STAMP:

SELECT a.`time_stamp`, a.`G1.state`, `G2.state` 
FROM `regs` AS `a` 
WHERE ((a.`G1.Estado` <> 
    (SELECT b.`G1.state` 
    FROM `regs` AS `b` 
    WHERE a.time_stamp > b.time_stamp 
    ORDER BY b.time_stamp DESC 
    LIMIT 1)) OR 
    (a.`G2.state` <> 
    (SELECT b.`G2.state` 
    FROM `regs` AS `b` 
    WHERE a.time_stamp > b.time_stamp 
    ORDER BY b.time_stamp DESC 
    LIMIT 1))) AND 
    (a.time_stamp >= 1433159549) AND (a.time_stamp < 1433677949) 
ORDER BY a.time_stamp ASC 

但是它只是需要太長時間運行,它需要50.96秒,我需要更快(希望不到一秒)。它分析了10k左右的值。任何人都可以在這裏給我一隻手嗎?

+0

您使用哪個dbms? (例如,LIMIT是特定產品...) – jarlh

+1

那麼對於那3行,你只想要最後一個返回? – jarlh

+0

請添加您的桌子上有哪些索引。 – whyte624

回答

2

可以使用變量在G1.stateG2.state列跟蹤更改:

SELECT time_stamp, `G1.state`, `G2.state` 
FROM (
SELECT time_stamp, `G1.state`, `G2.state`, 
     IF (@g1 IS NOT NULL AND @g1 <> `G1.state`, 
      IF(@g1:= `G1.state`, 1, 1), 
      IF(@g1:= `G1.state`, 0, 0)) AS g1Changed, 
     IF (@g2 IS NOT NULL AND @g2 <> `G2.state`, 
      IF(@g2:= `G2.state`, 1, 1), 
      IF(@g2:= `G2.state`, 0, 0)) AS g2Changed   
FROM mytable, (SELECT @g1:= NULL, @g2:= NULL) AS vars 
ORDER BY time_stamp ASC) t 
WHERE g1Changed = 1 OR g2Changed = 1 

,因爲沒有相關子查詢中使用該查詢可能會表現得更好。

注意:根據MariaDB documentation

這是不安全的讀取一個用戶定義的變量,並在同一語句中設置它的值(除非在命令置位),因爲這些動作的順序未定義。

爲了克服這個問題嵌套的條件被使用:@g1@g2分別第一針對G1.stateG2.state值進行比較,並且爲了然後集時的下一個記錄被取出再次比較。

Demo here

+0

您的查詢完美地工作,但我有一個問題。我第一次在控制檯中運行它時,它返回零值。然而,在第二次嘗試時,它有一些價值。當我使用php運行它時發生了同樣的事情,如果我運行它一次,我得到零值,但是,運行它兩次修復它。是否因爲需要首先聲明的變量? – Comum

+1

@Comum試試'FROM mytable,(SELECT @ g1:= NULL,@ g2:= NULL)AS vars'。見[這裏](http://sqlfiddle.com/#!9/32e60/9) –

+0

這樣做;)謝謝! – Comum

0
Select * from regs a 
Where time_stamp= 
    (Select Max(time_stamp) from regs 
     Where time_stamp< a.time_stamp) 
    and 'g1.state' <> a.'g1.staTE' 
order by a.time_stamp 
0

您可以使用索引加速查詢。最好的指數是

regs(time_stamp, `G1.state`, `G2.state`) 

注:這是真的不好的做法,在一列名稱中使用的字符,如.

+0

同上使用期間 –

+0

是的,當我得到這個工作,我開始改變所有的點。 – Comum

相關問題