2016-10-25 4 views
0

次の列を持つSQLテーブルがあります。これらの4行は1人のユーザー用です。その行85と86からuser_idrole_id最新明確な組み合わせを選択する速い方法だろう何SQL- 2つの列の最新の異なる組み合わせを選択してください

| id | user_id | role_id | preference_order | updated_at   | 
|----|---------|---------|------------------|---------------------| 
| 83 | 45  | 7  | 1    | 2016-10-24 03:29:18 | 
| 84 | 45  | 10  | 2    | 2016-10-24 03:29:18 | 
| 85 | 45  | 7  | 1    | 2016-10-25 05:40:18 | 
| 86 | 45  | 10  | 2    | 2016-10-25 05:40:18 | 


私が得ることができる最も近いこのクエリであるが、それは代わりに、行83と84を取得します。

SELECT * 
FROM user_role UR 
GROUP BY UR.user_id, UR.role_id 

私はまた、85と86を取得し、これを試してみましたが、それは大のために遅すぎるように見えました表:

SELECT * 
FROM user_role UR 
JOIN (SELECT user_id, role_id, max(updated_at) updated_at FROM user_role GROUP BY user_id, role_id) UR2 
    ON UR.user_id = UR2.user_id AND UR.role_id = UR2.role_id AND UR.updated_at = UR2.updated_at 
ORDER BY UR.order ASC; 
+0

を、あなたの第二のクエリの 'EXPLAIN'出力を共有していただけますか? – 1000111

+0

"where"条件または "Group by"に含まれる列のインデックスを確認しました – User

+0

遅すぎますか?インデックスを修正してください。 (user_id、role_id、updated_at、 'order')にインデックスを作成し、悪い 'SELECT *'は使わないでください。代わりに、実際に返される列に名前を付けます。最後に、orderは予約語であるため、テーブル/列識別子のために不適切な選択になっています。 – Strawberry

答えて

0

メイクROW_NUMBER(の使用)とuser_idの&ことによってそれを分割は

をROLE_ID
+0

もし10億行のテーブルを持っていれば、良いパフォーマンスが得られますか?私は完全なテーブルスキャンがここで起こると信じます – NzGuy

+0

'user_id、role_id、updated_at'カラムにインデックスがあることを確認してください。 – Squirrel

+0

@nzguy 10億行が多いので、パフォーマンスが悪くなる可能性があるので、「良い」は相対的です – Strawberry

-1
SELECT * 
FROM user_role UR 
    LEFT JOIN user_role UR2 ON UR.user_id=UR2.user_id 
          and UR.role_id=UR2.role_id 
          and UR.updated_at<UR2.updated_at 
WHERE UR2.updated_at IS NULL 
+0

問題は、これは恐ろしく遅いです。 – Strawberry

+0

@Strawberryなぜこれが遅くなるのか聞かせてもらえますか?インデックスが 'user_id、role_id、updated_at'の場合 – NzGuy

+0

@NzGuy合理的な質問ですが、私は正式に答えられません。私はこれが経験からそうであることを知っています。この種のクエリーは「イチゴクエリー」と呼ばれることがあるので、実際は悲劇的です。 – Strawberry

0

その後、サブクエリでupdate_atによるこの

  select 
      id , user_id , role_id , ord, updated_at 
      from 
      (
      SELECT * , 
      ROW_NUMBER() OVER (PARTITION BY ID ORDER BY pdated_at DESC) as RID 
      FROM user_role UR 
      )A 
      where RID in ('1','2') 
0

ため、メインクエリ内でグループを試してみてください。

select * from (
    select * from user_role order by user_id asc ,role_id asc,updated_at desc 
)UR GROUP BY UR.user_id, UR.role_id 
+0

ありがとう!これはうまくいきました:) – Zephyr

1

あなたが最大updated_atのに応じてROLE_ID複数のuser_id、必要な場合は、このクエリを試すことができます。

SELECT DISTINCT user_id,role_id,MAX(updated_at) from user_role group by user_id,role_id; 
+0

ありがとう、これは最新の 'updated_at'を持つユーザーの行だけを返すので、私は1人以上のユーザーを持っています:( – Zephyr

+0

私はクエリに編集を行いましたので確認してください。 – Kiran

0
SELECT DISTINCT * 
    FROM user_role 
     NATURAL JOIN 
     (SELECT user_id, role_id, 
       MAX(updated_at) AS updated_at 
      FROM user_role 
      GROUP 
      BY user_id, role_id) AS t; 
+0

ありがとう!私が望む行を選択:) – Zephyr

関連する問題