2013-10-07 7 views
8

私は複数列の主キー(都市/州/日付)とより多くのデータ列を持つテーブルを持っています。私は各都市/州の最新データを入手しようとしています。それをきれいに/効率的にどうやって行うのですか?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 
    ... 

これは本当に醜いと非効率的である。今、私は句巨大で2番目のクエリに続いて、私はフェッチしようとしているすべての行のリストを取得する最初のクエリを実行することによってこれを行うことができます最初のクエリが多くの行を返す場合、2番目のクエリが長すぎる可能性があります。明らかに、私が1列の主キーを持つ場合、IN()で副選択を使用することができますが、ここでは実際には可能ではありません。助言がありますか?

更新:私はBillの提案を副選択で試しましたが、キーを使用していないので、永遠に奪っています。 subselectが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

@ジョナサン - 私は助けてよかった。ここで実際に内部結合を使用することができますが、自然結合と同じ効果を得るには、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

を取得しようとしている結果とされているもの、私は彼がだったと思いますある場合は、ダイナミックなアプローチを探してみましょう - いくつかのhundretまたはテーブルに数千の都市を言う。 –

+0

@Bill:MySQLがタプル比較をサポートしていることは分かりませんでしたが、これは間違いなく答えの一部になりますが、GottliebNotschnabelは正しいです。私は動的な解決策が必要です。私は副選択でこれをやろうとしていますが、正しいキーを使用していません。 – Jonathan

+0

私はこれを前に試してみましたが、索引と一致する基準でさえもフルテーブルスキャンを行うようです。 – JasonMing

関連する問題