1

受信メッセージを格納するテーブルと送信メッセージを格納するテーブルの 2 つのテーブルがあります。私が望むのは、メッセージの会話ビューを表示できるようにして、同じユーザー ID との間のすべての送受信メッセージがグループ化され、会話が最新のメッセージ (インまたはアウト) によって順序付けられるようにすることです。

Outgoing
----------
user_id
time
message

Incoming
----------
user_id
time
message

私が望むのは、次のような結果を表示することです

-> User A   9:10 pm   Nice ...
<- User A   8:45 pm   Our special is pepperoni!
-> User A   8:00 pm   What's your special dish?

<- User B   9:00 pm   We open at 5
-> User B   6:56 pm   Hello What time to you open?

<- User C   8:43 pm   Thanks!
-> User C   4:00 pm   Loved the pizza today!!

これを行うためのクエリを作成する方法はありますか?

編集

ユーザー B がテキストを返信すると、結果は次のようになります。

-> User B   9:15 pm   Ok great!
<- User B   9:00 pm   We open at 5
-> User B   6:56 pm   Hello What time to you open?

-> User A   9:10 pm   Nice ...
<- User A   8:45 pm   Our special is pepperoni!
-> User A   8:00 pm   What's your special dish?

<- User C   8:43 pm   Thanks!
-> User C   4:00 pm   Loved the pizza today!!
4

4 に答える 4

2

UNION2 つのテーブルを並べ替え ( ORDER BY)、それに応じて次のようにする必要があります。

SELECT 
    '<-' AS direction,  user_id,  time,  message
FROM
    Outgoing

UNION ALL

SELECT 
    '->',               user_id,  time,  message
FROM
    Incoming

ORDER BY
    user_id ASC,
    time DESC ;

複雑な順序付けについての追加説明の後:

SELECT
  CASE WHEN m.d = 1 THEN '<-' ELSE '->' END AS direction, 
  m.user_id, m.time, m.message
FROM
    ( SELECT 
        u.user_id, 
        GREATEST( COALESCE(mo.time, mi.time), 
                  COALESCE(mi.time, mo.time) ) AS maxtime
      FROM 
          ( SELECT user_id  FROM Outgoing
          UNION
            SELECT user_id  FROM Incoming 
          ) AS u
        LEFT JOIN
          ( SELECT user_id, MAX(time) AS time  FROM Outgoing  GROUP BY user_id
          ) AS mo
          ON mo.user_id = u.user_id
        LEFT JOIN
          ( SELECT user_id, MAX(time) AS time  FROM Incoming  GROUP BY user_id
          ) AS mi
          ON mi.user_id = u.user_id
    ) AS b    
  JOIN
    ( SELECT 1 AS d, user_id, time, message  FROM Outgoing
    UNION ALL
      SELECT 2 AS d, user_id, time, message  FROM Incoming
    ) AS m
    ON m.user_id = b.user_id
ORDER BY
    b.maxtime ASC,
    m.user_id ASC,
    m.time DESC ;
于 2012-11-29T22:45:38.363 に答える
1

個人的には、テーブルをどのように構造化するかはあまり好きではありません。つまり、システム内のすべてのメッセージを各テーブルに複製する必要があります。

おそらく、to フィールドと from フィールドを持つメッセージ テーブルが 1 つだけあると思います。次のような単一のテーブルがある場合:

message_id (primary key)
from_user_id (indexed)
to_user_id (indexed)
message
time (indexed)

あなたのクエリは簡単です:

SELECT *
FROM messages
WHERE from_user_id = ? OR to_user_id = ?
ORDER BY time DESC

これは、表示している方法で表示するための簡単なクエリを提供しないことに注意してください(クエリ後のデータ操作を行う必要があります)。ただし、最も効率的なルックアップ クエリが提供され、ストレージ内でメッセージを 2 回複製する必要がなくなります。

グループ化された会話の概念に固執する必要がある場合 (またはマルチパーティ メッセージに拡張する必要がある場合) は、おそらく会話テーブルを見て、スキーマを次のように変更できます。

会話 (多対多の結合テーブル)

conversation_id (indexed)
user_id (indexed)
(compound primary key across both fields)

メッセージ

message_id (primary key)
conversation_id (indexed)
sending_user_id
message
time (indexed)

このようなクエリで

SELECT m.sending_user_id, m.message, m.time
FROM conversations AS c
INNER JOIN messages AS m ON c.conversation_id = m.conversation_id
WHERE c.user_id = ?
ORDER BY c.conversation_id, m.time DESC

結果クエリから明らかなように、sending_user_id が現在のユーザーの ID と等しい場合、それは発信メッセージであり、そうでない場合は、他の会話参加者の 1 人からのメッセージです。

于 2012-11-29T22:50:39.597 に答える
1

このようなものは、ユーザーと時間ごとに結果を取得する必要があります。ユーザーごとにメッセージを表示するには、アプリケーション レベルで表示を処理する必要があります。

select * from (
  select '->' as direction, o.* from outgoing o
  union
  select '<-' as direction, i.* from incoming i
) M
order by user_id asc, time desc

サンプル出力:

| DIRECTION | USER_ID |                            TIME |                      MESSAGE |
----------------------------------------------------------------------------------------
|        -> |       1 | November, 29 2012 21:10:00+0000 |                     Nice ... |
|        <- |       1 | November, 29 2012 20:45:00+0000 |    Our special is pepperoni! |
|        -> |       1 | November, 29 2012 20:00:00+0000 |   What''s your special dish? |
|        <- |       2 | November, 29 2012 21:00:00+0000 |                 We open at 5 |
|        -> |       2 | November, 29 2012 18:56:00+0000 | Hello What time to you open? |
|        <- |       3 | November, 29 2012 20:43:00+0000 |                      Thanks! |
|        -> |       3 | November, 29 2012 16:00:00+0000 |      Loved the pizza today!! |

デモ: http://www.sqlfiddle.com/#!2/602c1/11

于 2012-11-29T22:45:37.743 に答える
0

なぜテーブルを分けるのですか?それらを同じテーブルに配置し、1 と 0 が着信と発信を表すビット型の列を追加できます。次に、クエリは次のように単純です。

select user_id, time, message, inout from message order by user_id, time

私にとって方向性は、メッセージについて何かを伝えているのですが、いずれにせよ、それは依然としてメッセージです。

それでも他の方法で行う必要がある場合は、ユニオンを行う必要がありますが、パフォーマンスが低下することが予想されます。クエリに与えることができる最高のパフォーマンス調整は、事前にテーブルを設計することです。

with message as (
select user_id, time, message, 'incoming' from incoming
union all
select user_id, time, message, 'outgoing' from outgoing
) select * from message order by user_id, time

またはそのようなもの...

また、時間フィールドによる順序付けにも注意する必要があります。経験上、2 つのメッセージが同時に入ってくると、予期しない結果になることがわかります。これは、あなたの例が秒やマイクロ秒ではなく、分単位の粒度しかないため、特に可能性があります。より良い方法は、昇順で自動割り当てされる数値 PK を使用することです。そうすれば、時間が一意でない場合でも、順序を決定する方法があります。

于 2012-11-29T22:49:53.353 に答える