15

デートアプリケーションの場合、両方のクエリのLIMIT10を組み合わせて単一の出力をクエリする必要があるテーブルがいくつかあります。個別にクエリすることは問題ではありませんが、現時点では難しいようですが、数値が正確でないため、LIMIT 10は機能しません(たとえば、LIMIT5とLIMIT5ではなく、1つのクエリで0行が返される場合があります)。 、シナリオに応じて、他の10個)。

members table
member_id | member_name
------------------------
     1         Herb
     2         Karen
     3         Megan

dating_requests
request_id | member1 | member2 | request_time
----------------------------------------------------
     1          1         2      2012-12-21 12:51:45

dating_alerts
alert_id | alerter_id | alertee_id | type | alert_time
-------------------------------------------------------
    5           3            2     platonic  2012-12-21 10:25:32

dating_alerts_status
status_id | alert_id | alertee_id | viewed | viewed_time
-----------------------------------------------------------
     4          5           2          0      0000-00-00 00:00:00 

あなたがカレンでログインしたばかりだと想像してみてください。次の2つのアイテムが表示されます。

1. Herb requested a date with you.
2. Megan wants a platonic relationship with you.

LIMITが10の1つのクエリでは、代わりに、組み合わせる必要のある2つのクエリがあります。

1. Herb requested a date with you.
   -> query = "SELECT dr.request_id, dr.member1, dr.member2, m.member_name 
               FROM dating_requests dr 
               JOIN members m ON dr.member1=m.member_id 
               WHERE dr.member2=:loggedin_id 
               ORDER BY dr.request_time LIMIT 5";
2. Megan wants a platonic relationship with you.
   -> query = "SELECT da.alert_id, da.alerter_id, da.alertee_id, da.type,
                      da.alert_time, m.member_name
               FROM dating_alerts da
               JOIN dating_alerts_status das ON da.alert_id=das.alert_id
                    AND da.alertee_id=das.alertee_id
               JOIN members m ON da.alerter_id=m.member_id
               WHERE da.alertee_id=:loggedin_id AND da.type='platonic'
                     AND das.viewed='0' AND das.viewed_time<da.alert_time 
               ORDER BY da.alert_time LIMIT 5";

繰り返しになりますが、両方のテーブルが空であるか、1つのテーブルが空であるか、または両方がいっぱいで(LIMIT 10が開始される場合)、時間順に並べられている場合があります。このタスクを効率的に実行するためのクエリを取得する方法についてのアイデアはありますか?考え、アドバイス、チャイム、最適化は大歓迎です。

4

1 に答える 1

27

複数のクエリをと組み合わせることができますがUNION、クエリの列数が同じである場合に限ります。理想的には、列はデータ型だけでなく、意味も同じです。ただし、MySQLはセマンティクスを気にせず、より一般的なものにキャストすることでさまざまなデータ型を処理します。したがって、必要に応じて、列オーバーロードして各テーブルからさまざまな意味を持たせ、上位レベルのコードで適切な意味を判断できます。 (この方法はお勧めしませんが)。

列の数が異なる場合、または2つのクエリからのデータのオーバーロードの少ないアラインメントを実現したい場合は、ダミーのリテラル列をSELECTステートメントに挿入できます。例えば:

SELECT t.cola, t.colb, NULL, t.colc, NULL FROM t;

一部の列を最初のテーブル用に予約し、他の列を2番目のテーブル用に予約して、他の場所に配置することもできNULLます(ただし、列名は最初のクエリから取得されるため、すべての列に名前が付けられていることを確認してください)。

  SELECT a, b, c, d, NULL AS e, NULL AS f, NULL AS g FROM t1
UNION ALL -- specify ALL because default is DISTINCT, which is wasted here
  SELECT NULL, NULL, NULL, NULL, a, b, c FROM t2;

この方法で2つのクエリを整列させてから、それらをUNION演算子と組み合わせることができます。に適用LIMITすることでUNION、目標の達成に近づきます。

  (SELECT ...)
UNION
  (SELECT ...)
LIMIT 10;

残っている唯一の問題は、上記のように、最初のテーブルの10個以上のレコードが、2番目のテーブルのレコードを「プッシュ」することです。ORDER BYただし、これを解決するために外部クエリでを利用できます。

すべてを一緒に入れて:

(
  SELECT
    dr.request_time AS event_time, m.member_name,      -- shared columns
    dr.request_id, dr.member1, dr.member2,             -- request-only columns
    NULL AS alert_id, NULL AS alerter_id,              -- alert-only columns
      NULL AS alertee_id, NULL AS type
  FROM dating_requests dr JOIN members m ON dr.member1=m.member_id 
  WHERE dr.member2=:loggedin_id
  ORDER BY event_time LIMIT 10 -- save ourselves performing excessive UNION
) UNION ALL (
  SELECT
    da.alert_time AS event_time, m.member_name,        -- shared columns
    NULL, NULL, NULL,                                  -- request-only columns
    da.alert_id, da.alerter_id, da.alertee_id, da.type -- alert-only columns
  FROM
    dating_alerts da
    JOIN dating_alerts_status das USING (alert_id, alertee_id)
    JOIN members m ON da.alerter_id=m.member_id
  WHERE
    da.alertee_id=:loggedin_id
    AND da.type='platonic'
    AND das.viewed='0'
    AND das.viewed_time<da.alert_time
  ORDER BY event_time LIMIT 10 -- save ourselves performing excessive UNION
)
ORDER BY event_time
LIMIT 10;

もちろん、結果セットの各レコードを読み取るときに、処理している行のタイプを決定するのはあなた次第です(テストrequest_idや値のテストをお勧めalert_idします。またはNULL、結果に明示的に示す列を追加することもできます。各レコードはどのテーブルから発生したかですが、これらのid列が)である場合は同等である必要がありますNOT NULL

于 2012-04-25T22:53:37.633 に答える