他のテーブルにトリガーを配置し、User_Fansテーブルにいくつかの列を追加することでこの完全な単純化を試みます...取得しようとしているそれぞれのcount()ごとに1つ... Posts、PostLikes、PostComments、 PostCommentLikes。
レコードがどちらのテーブルに追加された場合でも、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
プレクエリへのLEFTJOINは、これらのクエリを1回実行します。その後、すべてのレコードのサブクエリとしてヒットされるのではなく、すべてが結合されます。 COALESCE()を使用すると、LEFT JOINedテーブルの結果にそのようなエントリがない場合、計算を台無しにするNULL値に見舞われることはないため、デフォルトで000000に設定しました。
質問の明確化
「ASAliasResult」として任意の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」にして、結果を使用する場所に単純化することができます。
selectCONCAT(User.Salutation、User.LastName)as CourtesyNamefrom ...
selectOrder.NonTaxable + Order.Taxable +(Order.Taxable * Order.SalesTaxRate)as OrderTotalWithTaxfrom ...
「As」columnNameは集計である必要はありませんが、最も一般的にはそのように表示されます。
さて、MySQL変数に関して...ストアドプロシージャを実行している場合、多くの人は、残りのプロシージャの前にデフォルト値を設定することを事前に宣言します。その結果に「エイリアス」参照を設定して指定するだけで、クエリでインラインでそれらを実行できます。これらの変数を実行する場合、selectは常にSINGLERECORDに相当する値を返すことをシミュレートします。これは、クエリ内で使用される更新可能な単一のレコードとほとんど同じです。クエリ内の残りのテーブルとは関係がない可能性があるため、特定の「結合」条件を適用する必要はありません...本質的に、デカルト結果を作成しますが、他のテーブルに対する1つのレコードは作成されません。とにかく複製するので、下流に損傷はありません。
select
...
from
( select @SomeVar := 0,
@SomeDate := curdate(),
@SomeString := "hello" ) as SQLVars
ここで、sqlvarsがどのように機能するかを説明します。線形計画法を考えてみてください...クエリの実行時に、1つのコマンドが正確な順序で実行されます。その後、その値は「SQLVars」レコードに再保存され、次回の準備が整います。ただし、SQLVars.SomeVarまたはSQLVars.SomeDate ...として参照するのではなく、@ SomeVar:=someNewValueとして参照します。これで、@ varがクエリで使用されると、結果セットに「AsColumnName」としても保存されます。場合によっては、これは次のレコードの準備でのプレースホルダーの計算値にすぎないことがあります。各値は、次の行で直接使用できます。したがって、次のサンプルが与えられます...
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
「OrderBy」句は、結果を最初に順番に返すように強制します。したがって、ここでは、顧客ごとのレコードが返されます。初めての場合、LastIDは0で、顧客IDは次のようになります...5。異なるため、@ SeqNoとして1を返し、その顧客IDを次のレコードの@LastIDフィールドに保持します。さて、顧客の次のレコード...最後のIDは同じなので、@ SeqNo(現在=1)を取り、1を1に加算して、同じ顧客の#2になります...パスを続行します。 。
クエリの記述を上手に行うために、MySQLタグを見て、大きな貢献者のいくつかを見てください。質問といくつかの複雑な答え、および問題解決がどのように機能するかを調べてください。始めたばかりで完全に有能な評判スコアの低い人がいないことは言うまでもありませんが、誰が良い答えを出し、その理由はわかります。投稿された回答の履歴も見てください。読んで従うほど、より複雑なクエリを書く際の扱いが良くなります。