2

投稿が保存されるテーブル「gems」があります(ブログなど)。投稿への返信も、親投稿のキーを格納するフィールドとともに同じテーブルに格納されます。各投稿にはファイルを添付できます。

返信と添付ファイルが関連付けられた投稿のリストを取得する必要があります。したがって、「gems」には複数の左結合があります。1つはそれ自体に、もう1つはファイル名とともに「gemdetail」になります。このクエリは機能します:

SELECT g.gemid as gemidx, g.title, gemdetail.filename, r.gemid as rgemid, r.title, r.filename
FROM (SELECT * FROM gems WHERE gems.grade = '7' LIMIT 0, 10) g 
LEFT JOIN (SELECT x.title, x.gemid, x.replygemid, y.filename from gems x 
    LEFT JOIN gemdetail y ON x.gemid = y.gemid ) r ON g.gemid = r.replygemid 
LEFT JOIN gemdetail ON g.gemid = gemdetail.gemid 

ただし、投稿ごとに20の返信と10のファイルがある場合、返されるレコードの数は投稿ごとに200になります。LIMIT句は機能しますが、これはまだ多くのレコードです。さらに、レコードセットを扱うのはクマです。

投稿ごとに(200ではなく)40レコードのみを返すUNIONを使用するようにクエリを書き直しました。UNIONには4つの部分があります-1)最初の10レコードを返します(LIMIT)2)投稿のファイル名を取得します3)返信を取得します4)返信のファイル名を取得します

以下のUNIONクエリは、UNIONの最初の部分以外で返されるレコードの数を制限できないことを除いて機能します。UNIONの各部分にLIMITステートメントを入れることはできますが、これは正しくありません(ファイルと返信をLIMITED 10の投稿のセットに制限したい)。いずれかのUNIONにWHEREgemidIN(SELECT gemid from gems ....)句を使用しようとすると、mySQLサブクエリ制限エラーが発生します。

SELECT g.gemid as gemidx, g.title, NULL as filename, NULL as rgemid, 'ag' as flag 
FROM (SELECT * FROM gems WHERE ISNULL(gems.replygemid) AND gems.grade = '7' LIMIT 0, 10) g
LEFT JOIN (SELECT * FROM gems) r ON g.gemid = r.replygemid  

UNION SELECT g.gemid as gemidx, g.title, gemdetail.filename as filename, NULL as rgemid, 'bf' as flag 
FROM (SELECT * FROM gems WHERE ISNULL(gems.replygemid) AND gems.grade = '7') g 
INNER JOIN gemdetail ON g.gemid = gemdetail.gemid

UNION SELECT g.replygemid as gemidx, g.title, NULL as filename, g.gemid as rgemid, 'cr' as flag 
FROM (SELECT * FROM gems WHERE NOT ISNULL(gems.replygemid) AND gems.grade = '7') g 

UNION SELECT g.replygemid as gemidx, g.title, gemdetail.filename as filename, g.gemid as rgemid, 'df' as flag 
FROM (SELECT * FROM gems WHERE NOT ISNULL(gems.replygemid) AND gems.grade = '7') g 
INNER JOIN gemdetail ON g.gemid = gemdetail.gemid 

ORDER BY gemidx desc, rgemid, flag

助けてください。(ページネーションのために)10件の投稿とそれに関連するすべての返信とファイルのみを効率的に選択する方法はありますか?これをお読みいただきありがとうございます。私はこれに2日間を費やし、限界に達しています(お粗末なしゃれが意図されています...)。

4

1 に答える 1

0

ちょっとした遊びですが、このコードはちょっと厄介なので、使いたくないかもしれません。ただし、これは今のところファイルを無視しています。私は自分のテーブルで動作するようなものを取得し、それからこれを導出しましたが、これを直接テストしていないため、タイプミスがある可能性があることに注意してください。

SELECT gems.gemid as gemidx, gems.title, r.gemid as rgemid, r.title, r.filename
FROM gems
INNER JOIN (SELECT gems.*, @runningtotal:=@runningtotal+1 AS CurrentTotal
FROM (SELECT @runningtotal := 0)Deriv1, gems 
ORDER BY replygemid) r
INNER JOIN (SELECT replygemid, MIN(CurrentTotal) AS MinTotal
FROM (SELECT replygemid, @runningtotal:=@runningtotal+1 AS CurrentTotal
FROM (SELECT @runningtotal := 0)Deriv1, gems 
ORDER BY replygemid) Deriv2
GROUP BY replygemid) Deriv5
ON Deriv4.replygemid = Deriv5.replygemid 
AND Deriv4.CurrentTotal < Deriv5.MinTotal + 10
WHERE gems.grade = '7'

これが行っていることは、副選択を使用して、応答にシーケンス番号を追加することです (親によって順序付けられます)。この副選択を 2 回使用します。1 回目はグループの最小シーケンス番号を取得するため、2 回目はすべての行の詳細をシーケンス番号とともに戻します。次に、これを JOIN して、シーケンス番号がその gem の最初の 10 のうちの 1 つであるものを取得します。

私は物事を単一の SQL の中に収めることを好みますが、これは遅すぎて価値がない段階に達していると思います。

GROUP_CONCAT を使用してファイルの詳細を入れて、gem の返信用にそれらすべてを追加し、コードで興味のないもの (つまり、10 以上) を破棄することが可能かもしれません。

申し訳ありませんが、これ以上役立つものは思いつきません

于 2012-12-03T13:34:10.800 に答える