2013-10-07 47 views
8

我有一個多列主鍵(城市/州/日期)和更多列的數據表。我正在尋找每個城市/州的最新數據。我該如何幹淨/有效地做到這一點?現在,我可以做第一查詢來獲取所有我想要獲取的行列表做到這一點,然後用大量的第二個查詢的WHERE子句:如何在MySQL中通過多列主鍵選擇多行?

SELECT state, city, max(date) from data GROUP BY city, state; 

+-------+---------------------+------------+ 
| state | city    | MAX(date) | 
+-------+---------------------+------------+ 
| CA | San Francisco  | 2013-09-01 | 
| CA | Los Angeles   | 2013-08-01 | 
| NY | New York   | 2013-10-01 | 
| ... | ... (many rows) ... | ...  | 
+-------+---------------------+------------+ 


SELECT * FROM data WHERE 
    (state = "CA" AND city = "San Francisco" AND date='2013-09-01') OR 
    (state = "CA" AND city = "Los Angeles" AND date='2013-08-01') OR 
    (state = "NY" AND city = "New York" AND date='2013-10-01') OR 
    ... 

這實在是太醜了,效率低下,如果第一個查詢返回很多行,那麼我的第二個查詢可能太長。很明顯,如果我有一個單列主鍵,我可以使用IN()的子查詢,但這在這裏不太可能。有什麼建議麼?

更新:我試着比爾的推薦與子選擇,但它沒有使用任何鍵,並採取永遠。如果我限制子查詢返回5行,它返回0.64s。如果我讓它返回所有73個城市/州組合,則需要很長時間(查詢仍在運行)。

EXPLAIN SELECT * FROM data WHERE (city, state, date) IN (SELECT state, city, MAX(date) FROM data GROUP BY city, state) 
+----+--------------------+-------+-------+---------------+---------+---------+------+-------+-------------+ 
| id | select_type  | table | type | possible_keys | key  | key_len | ref | rows | Extra  | 
+----+--------------------+-------+-------+---------------+---------+---------+------+-------+-------------+ 
| 1 | PRIMARY   | data | ALL | NULL   | NULL | NULL | NULL | 13342 | Using where | 
| 2 | DEPENDENT SUBQUERY | data | index | NULL   | PRIMARY | 57  | NULL | 8058 | Using index | 
+----+--------------------+-------+-------+---------------+---------+---------+------+-------+-------------+ 
+1

結局是什麼導致你正試圖獲得 – Ibu

回答

4

我認爲這應該爲您做的伎倆:

select 
    * 
from 
    data t1 
natural join 
    ( 
     select 
      city, 
      state, 
      max(date) as date 
     from 
      data 
     group by 
      city, 
      state 
    ) t2; 
+0

是的,這是完美的作品!我以前從未使用過自然連接,但這正是我想要的,而且速度很快! – Jonathan

+0

@Jonathan - 很高興能幫到你。實際上你可以在這裏使用內部連接,但是你必須在所有3列上寫'on'子句以獲得與自然連接相同的效果。這種方式更加清晰,對於自然連接可能會快一點,對於公共列將只有1個副本,但內部連接會生成其中的2個副本。 –

4

MySQL支持的元組比較,:

SELECT * FROM data WHERE 
(state, city, date) IN (
    ('CA', 'San Francisco', '2013-09-01'), 
    ('CA', 'Los Angeles', '2013-08-01'), 
    ('NY', 'New York', '2013-10-01')); 
+0

我認爲他是如果有的話 - 尋找一個動態的方法 - 幾張或幾千個城市。 –

+0

@Bill:我不知道MySQL支持元組比較,這肯定會成爲答案的一部分,但GottliebNotschnabel是正確的,我確實需要一個動態解決方案。我試圖用一個子選擇來做到這一點,但它沒有使用正確的鍵。 – Jonathan

+0

我以前試過這個,好像會做全表掃描甚至是標準匹配索引。 – JasonMing