他のテーブルにトリガーを配置し、 User_Fans テーブルにいくつかの列を追加するだけで、これを完全に簡素化しようとします...取得しようとしているそれぞれの count() ごとに1つ... Posts、PostLikes、PostComments、投稿コメントいいね。
どちらのテーブルにレコードが追加された場合でも、user_fans テーブルを更新してカウントに 1 を追加するだけです。とにかく、ユーザーのキー ID に基づいて事実上瞬時に行われます。「LIKES」については... 同様に、何かが「Like」としてトリガーされるという条件の下でのみ、1 を追加します「加重」合計値。テーブルがさらに大きくなると、流し込んで集計するデータが増えるため、クエリも長くなります。本質的に他のすべてのテーブルからすべてのレコードを照会しているすべての user_fan レコードを通過しています。
そうは言っても、テーブルをそのままにして、次のように再構築します...
SELECT
uf.user_name,
uf.user_id,
@pc := coalesce( PostSummary.PostCount, 000000 ) as PostCount,
@pl := coalesce( PostLikes.LikesCount, 000000 ) as PostLikes,
@cc := coalesce( CommentSummary.CommentsCount, 000000 ) as PostComments,
@cl := coalesce( CommentLikes.LikesCount, 000000 ) as CommentLikes,
@pc + @cc AS sum_post,
@pl + @cl AS sum_like,
@pCalc := (@pc + @cc) * 10 AS post_cal,
@lCalc := (@pl + @cl) * 5 AS like_cal,
@pCalc + @lCalc AS `total`
FROM
( select @pc := 0,
@pl := 0,
@cc := 0,
@cl := 0,
@pCalc := 0
@lCalc := 0 ) sqlvars,
user_fans uf
LEFT JOIN ( select user_id, COUNT(*) as PostCount
from post
group by user_id ) as PostSummary
ON uf.user_id = PostSummary.User_ID
LEFT JOIN ( select user_id, COUNT(*) as LikesCount
from post_likes
group by user_id ) as PostLikes
ON uf.user_id = PostLikes.User_ID
LEFT JOIN ( select user_id, COUNT(*) as CommentsCount
from post_comment
group by user_id ) as CommentSummary
ON uf.user_id = CommentSummary.User_ID
LEFT JOIN ( select user_id, COUNT(*) as LikesCount
from post_comment_likes
group by user_id ) as CommentLikes
ON uf.user_id = CommentLikes.User_ID
ORDER BY
`total` DESC
LIMIT 20
My variables are abbreviated as
"@pc" = PostCount
"@pl" = PostLikes
"@cc" = CommentCount
"@cl" = CommentLike
"@pCalc" = weighted calc of post and comment count * 10 weighted value
"@lCalc" = weighted calc of post and comment likes * 5 weighted value
プレクエリへの LEFT JOIN は、これらのクエリを 1 回実行し、すべてのレコードのサブクエリとしてヒットする代わりに、全体が結合されます。COALESCE() を使用すると、LEFT JOIN されたテーブルの結果にそのようなエントリがない場合、NULL 値でヒットして計算が台無しになることはないので、デフォルトで 000000 に設定しました。
ご質問の明確化
「AS AliasResult」として任意の QUERY を持つことができます。"As" を使用して、長いテーブル名を簡略化し、読みやすくすることもできます。エイリアスは、同じテーブルを別のエイリアスとして使用して、同様のコンテンツを別の目的で取得することもできます。
select
MyAlias.SomeField
from
MySuperLongTableNameInDatabase MyAlias ...
select
c.LastName,
o.OrderAmount
from
customers c
join orders o
on c.customerID = o.customerID ...
select
PQ.SomeKey
from
( select ST.SomeKey
from SomeTable ST
where ST.SomeDate between X and Y ) as PQ
JOIN SomeOtherTable SOT
on PQ.SomeKey = SOT.SomeKey ...
現在、上記の 3 番目のクエリは実用的ではありません (完全なクエリの結果、"PreQuery" を表すエイリアス "PQ" が生成されます)。これは、他の複雑な条件の特定のセットを事前に制限し、すべての最終結果のために他の多くのテーブルに追加の結合を行う前に、より小さなセットが必要な場合に実行できます。
「FROM」は実際のテーブルである必要はありませんが、それ自体がクエリである可能性があるため、クエリで使用される他の場所では、このプレクエリの結果セットを参照する方法を知っている必要があります。
また、フィールドをクエリする場合、それらも「As FinalColumnName」にすることで、結果がどこで使用されるかを単純化できます。
... から CourtesyName として CONCAT( User.Salutation, User.LastName ) を選択します。
... から OrderTotalWithTax として Order.NonTaxable + Order.Taxable + ( Order.Taxable * Order.SalesTaxRate ) を選択します。
"As" columnName は集約である必要はありませんが、最も一般的にはそのように見られます。
ここで、MySQL 変数に関して... ストアド プロシージャを実行している場合、多くの人は、プロシージャの残りの部分の前にデフォルト値を設定することを事前に宣言します。その結果に「エイリアス」参照を設定して与えるだけで、クエリでインラインで実行できます。これらの変数を実行すると、select は常に SINGLE RECORD 相当の値を返すことをシミュレートします。クエリ内で使用される更新可能な単一のレコードに似ています。クエリ内の残りのテーブルに影響を与えない可能性があるため、特定の「結合」条件を適用する必要はありません...本質的に、デカルト結果を作成しますが、他のテーブルに対する1つのレコードは作成されませんとにかく重複するので、下流にダメージはありません。
select
...
from
( select @SomeVar := 0,
@SomeDate := curdate(),
@SomeString := "hello" ) as SQLVars
さて、sqlvars がどのように機能するか。線形プログラムを考えてみてください... クエリの実行とまったく同じ順序で 1 つのコマンドが実行されます。その値は、次回に備えて "SQLVars" レコードに再格納されます。ただし、SQLVars.SomeVar または SQLVars.SomeDate として参照するのではなく、単に @SomeVar := someNewValue として参照します。これで、@var がクエリで使用されると、結果セットにも "As ColumnName" として格納されます。場合によっては、これは次のレコードを準備するための単なるプレースホルダーの計算値になることがあります。各値は、次の行で直接使用できます。したがって、次のサンプルを考えると...
select
@SomeVar := SomeVar * 2 as FirstVal,
@SomeVar := SomeVar * 2 as SecondVal,
@SomeVar := SomeVar * 2 as ThirdVal
from
( select @SomeVar := 1 ) sqlvars,
AnotherTable
limit 3
Will result in 3 records with the values of
FirstVal SecondVal ThirdVal
2 4 8
16 32 64
128 256 512
@SomeVar の値が各列で使用されるときにどのように使用されるかに注意してください...したがって、同じレコードであっても、更新された値は次の列ですぐに利用できます... / お客様ごとのランキング...
select
o.CustomerID,
o.OrderID
@SeqNo := if( @LastID = o.CustomerID, @SeqNo +1, 1 ) as CustomerSequence,
@LastID := o.CustomerID as PlaceHolderToSaveForNextRecordCompare
from
orders o,
( select @SeqNo := 0, @LastID := 0 ) sqlvars
order by
o.CustomerID
「Order By」句は、結果が最初に順番に返されるように強制します。したがって、ここでは、顧客ごとのレコードが返されます。初めて、LastID は 0 で、顧客 ID は ...5 です。異なるため、@SeqNo として 1 を返し、その顧客 ID を次のレコードの @LastID フィールドに保存します。さて、顧客の次のレコード... 最後の ID は同じなので、@SeqNo (現在 = 1) を取り、1 に 1 を追加して、同じ顧客の #2 になります... パスを続行します.. .
クエリの書き方を改善するために、MySQL タグを見て、いくつかの重要な貢献者を調べてください。質問といくつかの複雑な回答、および問題解決のしくみを調べます。始めたばかりで完全に有能で評判スコアが低い人が他にいないことは言うまでもありませんが、誰が良い答えを出し、その理由を見つけることができます. 投稿された回答の履歴も見てください。読んでフォローすればするほど、より複雑なクエリをより適切に記述できるようになります。