2010-11-22 10 views
0

私は3つのテーブルを持っているとしましょう:ユーザ、クイズ、質問。それぞれにはid(整数)フィールドとcreated_at(datetime)フィールドがあります。私は、これらのテーブルをまとめて、created_at descでソートしてから、例えばページが10個のレコードであるレコードの「ページ」を得ることができます。つまり、これらの3つのテーブルのいずれかから最近作成された10個のレコードを取得したいと考えています。Mysql(一般的なsql?):3つの無関係なテーブルを同じフィールドでソート

私の最初の考えは、外部結合を行うことだけですが、これは非常に効率的ではない大規模な結合テーブルになります。また、基本的には間違っています。私はすべてのレコードを結合したくないので、すべてをまとめて1つのリストにまとめるだけです。再び、のいずれかとして

select users.id, users.created_at, quizzes.id, quizzes.created_at, concat(users.created_at, quizzes.created_at) from users, quizzes order by concat(users.created_at, quizzes.created_at) desc limit 5; 

しかし、これは動作しません:

は、私はそれからちょうど(ちょうどそれをテストするための2つのテーブル)from句に両方のテーブルを置くとテーブルを注文するcomcatを使用してみました、2つのテーブルが結合され、クエリを実行するのに時間がかかります(10秒間)。さらに、concatは私が考える正しいアプローチではありません。

誰でも私がやろうとしていることを見て、私を助けてくれますか?私はそれがとてもよく、月曜日の朝の症候群をおそらく説明していないように感じる。歓声、最大

編集 - ここに私の解決、Tomalakの答えの調整版です。私はcreated_atではなくupdated_atフィールドを使用していますが、それは別のdatetimeフィールドです。

私がトーマラックの答えで持っていた問題は、各レコードがどのテーブルから来たのかを追跡できないことでした。上の例では、テーブル名をIDの先頭に連結するので、次のようなものになります。

+---------------+---------------------+ 
| id   | updated_at   | 
+---------------+---------------------+ 
| user_1  | 2010-11-23 16:38:11 | 
| quiz_1306  | 2010-11-23 10:37:49 | 
| user_2  | 2010-11-22 11:57:08 | 
| user_401  | 2010-11-22 11:48:20 | 
| quiz_1303  | 2010-11-22 11:47:53 | 
| question_5163 | 2010-11-22 11:42:20 | 
| question_5162 | 2010-11-22 11:42:16 | 
| question_5161 | 2010-11-22 11:37:11 | 
| question_5160 | 2010-11-22 11:34:55 | 
| quiz_1304  | 2010-11-22 11:31:54 | 
+---------------+---------------------+ 
10 rows in set (0.16 sec) 

答えて

1

このようにします。クエリ効率の点で

SELECT 
    tbl, id, updated_at 
FROM 
    (
    SELECT 'users' AS tbl, id, updated_at FROM users 
    UNION 
    SELECT 'quizzes',  id, updated_at FROM quizzes 
    UNION 
    SELECT 'questions', id, updated_at FROM questions 
) as everything 
ORDER BY 
    updated_at DESC 
LIMIT 10; 

、それはこのバリアントは速く走ることが考えられます。

SELECT 
    tbl, id, updated_at 
FROM 
    (
    SELECT 'users' AS tbl, id, updated_at 
    FROM  users 
    ORDER BY updated_at DESC LIMIT 10 
    UNION 
    SELECT 'quizzes',  id, updated_at 
    FROM  quizzes 
    ORDER BY updated_at DESC LIMIT 10 
    UNION 
    SELECT 'questions',  id, updated_at 
    FROM  questions 
    ORDER BY updated_at DESC LIMIT 10 
) as everything 
ORDER BY 
    updated_at DESC 
LIMIT 10; 

あなたは、個々のテーブルの上に(updated_at, id)のインデックスを持つ必要があります。

と同様ににはすでにソートされているインデックスを調べることによってクエリを完全に実行できます。idフィールドが含まれています。出力にフィールドを追加しない限り、元のテーブルを参照する必要はありません。さらに、「外側」のORDER BY(インデックスを使用できない)は、30行だけソートする必要があります。

+0

ありがとうTomalak、それは働いた!私が持っていた次の問題は、「どのテーブルが各テーブルから来たのか、どのように知っていますか?私はこれを理解することができました。おそらくそれほど巧妙ではない方法で、この解決策を私のOPに編集しました。 –

+0

@Max Williams:あなたは近くにいた。私の変更された答えを見てください。 – Tomalak

関連する問題