1

チケット、ticketThreads、users、および threadStatus テーブルをクエリする次の SQL クエリがあります。

SELECT tickets.threadId, ticketThreads.threadSubject, tickets.ticketCreatedDate,  ticketThreads.threadCreatedDate, threadStatus.threadStatus, users.name
FROM 
tickets 
INNER JOIN 
ticketThreads
ON
tickets.threadId = ticketThreads.threadId
INNER JOIN
threadStatus 
ON
ticketThreads.threadStatus = threadStatus.id
INNER JOIN
users
ON
users.id = ticketThreads.threadUserId
WHERE
tickets.ticketId = ticketThreads.lastMessage
AND 
ticketThreads.threadStatus != 3
ORDER BY
tickets.ticketCreatedDate
DESC

これが返すものの要約版は次のとおりです。

threadId | 
----------
1        |
2        |

これは問題なく動作し、期待どおりですが、コードとデータベースを少しクリーンアップするには、 ticketThreads.lastMessage 列を削除する必要があります。

行を削除するとWHERE tickets.ticketId = ticketThreads.lastMessage、これは返されるものの要約版です。

threadId | 
----------
1        |
2        |
1        |

次に行う必要があるのは、上記のクエリを編集して、チケット データベース内の各 threadId 値に対して最大の一意の値を選択できるようにすることです。

私は知ってMAX()GROUP BYますが、上記のクエリにそれらを取り込む方法を理解できません。

表の関連部分を以下に示します。

切符売場

ticketId | ticketUserId | threadId 
-------------------------------
1        | 1            | 1
2        | 1            | 2
3        | 1            | 1

チケットスレッド

threadId | lastMessage  | threadStatus
-------------------------------
1        | 3            | 4
2        | 2            | 1

上記のすべてが明確で理にかなっていることを願っています

4

1 に答える 1

3

ticketでは、各スレッドごとに最高の IDが必要ですか? あなたの問題は、実際にはグループごとの最大記録の問題の非常に簡単な変形です。サブクエリは必要ありません。基本的に、2 つのオプションがあり、どちらもクエリよりもはるかに優れたパフォーマンスを発揮します。

1. 標準に準拠したクエリですが、低速です:

SELECT t1.threadId, ticketThreads.threadSubject, t1.ticketCreatedDate,  
    ticketThreads.threadCreatedDate, threadStatus.threadStatus, users.name
FROM tickets as t1
LEFT JOIN tickets as t2 
    ON t1.threadId = t2.threadId AND t1.ticketId < t2.ticketId
JOIN ticketThreads ON t1.threadId = ticketThreads.threadId
JOIN threadStatus ON ticketThreads.threadStatus = threadStatus.id
JOIN users ON users.id = ticketThreads.threadUserId
WHERE t2.threadId is NULL
    AND ticketThreads.threadStatus != 3
ORDER BY t1.ticketCreatedDate DESC

これはテーブルを 2 回結合するticketsため、大きなテーブルでは少し遅くなる可能性があります。

2. より高速ですが、標準 SQL に対する MySQL 拡張機能を使用します。

set @prev_thread := NULL;

SELECT t.threadId, ticketThreads.threadSubject, t.ticketCreatedDate,  
    ticketThreads.threadCreatedDate, threadStatus.threadStatus, users.name
FROM tickets as t
JOIN ticketThreads ON t.threadId = ticketThreads.threadId
JOIN threadStatus ON ticketThreads.threadStatus = threadStatus.id
JOIN users ON users.id = ticketThreads.threadUserId
WHERE ticketThreads.threadStatus != 3
    AND IF(IFNULL(@prev_thread, -1) = @prev_thread := t.threadId, 0, 1)
ORDER BY t.threadId, t.ticketId DESC,
    t.ticketCreatedDate DESC

ここでは、補助的な mysql 変数@prev_threadを使用して、各スレッドの最初の (指定された順序で) チケット (最も高い ticketId を持つチケット) のみをフィルター処理し、順序付けられた結合データに対して 1 つのパス スキャンを実行します。

于 2013-07-17T19:02:28.277 に答える