groupBy和orderBy的替代方案

1、背景

相關的設備狀態數據

在開發的時候遇到一個需求,須要根據device_code將數據分組,同時得到每組數據中最新的一條數據。sql

2、遇到的問題

2.1 最初的思路:先對數據進行orderBy 再進行groupBy
sql語句:
 sql: SELECT * from y_device_events ORDER BY created_at DESC GROUP BY device_code

結果: 這種寫法會報錯,當groupBy和orderBy組合使用的時候,必需要先進性groupBy在進行orderBy。spa

2.2 進階思路:對數據進行orderBy的結果做爲臨時表,再對臨時表分組
sql語:
 sql:SELECT * from (SELECT * from y_device_events ORDER BY created_at DESC) as new_table GROUP BY new_table.device_code

結果:這條語句執行了,可是結果並無按照預期的將最新的一條篩選出來code

3、最終的解決方案

3.1 初級方案

經過以前兩種方案發現直接使用orderBy和groupBy並不能達到目的,最後以爲能夠和自身做關聯查詢,經過關聯查詢進行篩選。blog

SELECT
`y_device_events`.*
FROM
`y_device_events`
LEFT JOIN `y_device_events` AS `new_table` ON `y_device_events`.`device_code` = 
`new_table`.`device_code`
AND `y_device_events`.`created_at` < `new_table`.`created_at`
WHERE
`new_table`.`created_at` IS NULL

這種方法經過左關聯查詢,對笛卡爾積進行了篩選,就能夠達到咱們的目的。開發

3.2 缺點:對於數據量特別大的狀況,若是沒有限制條件,獲得的笛卡爾積會很大,因此查詢速度較慢。
3.3 最終的寫法

個人需求中能夠加上對type及sub_type的限制,所以稍微能夠加快一下數據的篩選,並且若是有數據篩選條件,能夠將條件放入JOIN語句裏面,而不是join完成的where裏it

SELECT
  `y_device_events`.*
FROM
  `y_device_events`
LEFT JOIN `y_device_events` AS `new_table` ON `y_device_events`.`device_code` = 
`new_table`.`device_code`
AND `y_device_events`.`created_at` < `new_table`.`created_at`
AND `y_device_events`.`type` = `new_table`.`type`
AND `y_device_events`.`sub_type` = `new_table`.`sub_type`
AND `y_device_events`.`type` = `2`
AND `y_device_events`.`sub_type` = `1`
WHERE
 `new_table`.`created_at` IS NULL
AND `y_device_events`.`created_at` > '2018 - 07 - 05 10 : 07 : 27'
AND `y_device_events`.`created_at` < '2018 - 07 - 05 11 : 04 : 27'
AND `y_device_events`.`result_code` = '-1'

加入篩選條件後,能夠大大加快查詢的效率。event

相關文章
相關標籤/搜索