Saya akan mencoba menyederhanakan ini SEPENUHNYA dengan meletakkan pemicu di tabel Anda yang lain, dan hanya menambahkan beberapa kolom ke tabel User_Fans Anda... Satu untuk setiap count() masing-masing yang Anda coba dapatkan... dari Posting, PostLikes, PostComments, PostCommentLikes.
Ketika sebuah catatan ditambahkan ke tabel mana pun, cukup perbarui tabel user_fans Anda untuk menambahkan 1 ke hitungan... bagaimanapun, itu akan hampir seketika berdasarkan ID kunci pengguna. Adapun "LIKES"... Serupa, hanya dengan syarat bahwa sesuatu dipicu sebagai "Suka", tambahkan 1.. Kemudian kueri Anda akan menjadi matematika langsung pada catatan tunggal dan tidak bergantung pada APAPUN bergabung untuk menghitung nilai total "tertimbang". Saat tabel Anda semakin besar, kueri juga akan menjadi lebih panjang karena memiliki lebih banyak data untuk dituangkan dan dikumpulkan. Anda akan melalui SETIAP catatan user_fan yang intinya adalah menanyakan setiap catatan dari semua tabel lainnya.
Semua yang dikatakan, menjaga tabel seperti yang Anda miliki, saya akan merestrukturisasi sebagai berikut...
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 to prequeries menjalankan kueri tersebut SEKALI, lalu semuanya digabungkan alih-alih dipukul sebagai sub-kueri untuk setiap catatan. Dengan menggunakan COALESCE(), jika tidak ada entri seperti itu di hasil tabel LEFT JOINed, Anda tidak akan mendapatkan nilai NULL yang mengacaukan perhitungan, jadi saya menetapkannya ke 000000.
KLARIFIKASI PERTANYAAN ANDA
Anda dapat memiliki QUERY sebagai "AS AliasResult". "As" juga dapat digunakan untuk menyederhanakan nama tabel yang panjang agar mudah dibaca. Alias juga dapat menggunakan tabel yang sama tetapi sebagai alias berbeda untuk mendapatkan konten serupa, tetapi untuk tujuan yang berbeda.
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 ...
Sekarang, kueri ketiga di atas tidak praktis membutuhkan ( kueri penuh menghasilkan alias "PQ" mewakili "PreQuery" ). Ini dapat dilakukan jika Anda ingin membatasi serangkaian kondisi kompleks lainnya sebelumnya dan menginginkan set yang lebih kecil SEBELUM melakukan penggabungan ekstra ke banyak tabel lain untuk semua hasil akhir.
Karena "FROM" tidak HARUS menjadi tabel yang sebenarnya, tetapi dapat berupa kueri itu sendiri, tempat lain yang digunakan dalam kueri, ia harus tahu cara mereferensikan kumpulan hasil prakueri ini.
Selain itu, saat menanyakan bidang, bidang tersebut juga dapat berupa "Sebagai NamaKolom Akhir" untuk menyederhanakan hasil ke mana pun bidang tersebut akan digunakan.
pilihCONCAT( User.Salutation, User.LastName ) sebagai CourtesyNamefrom ...
pilihOrder.NonTaxable+ Order.Taxable+ ( Order.Taxable * Order.SalesTaxRate ) sebagai OrderTotalWithTaxfrom ...
Nama kolom "Sebagai" TIDAK diperlukan sebagai agregat, tetapi paling sering terlihat seperti itu.
Sekarang, sehubungan dengan variabel MySQL... Jika Anda melakukan prosedur tersimpan, banyak orang akan mendeklarasikan sebelumnya bahwa mereka menetapkan nilai default sebelum prosedur lainnya. Anda dapat melakukannya sebaris dalam kueri hanya dengan menyetel dan memberikan referensi "Alias" pada hasil tersebut. Saat melakukan variabel ini, pilih akan mensimulasikan selalu mengembalikan nilai SINGLE RECORD senilai. Ini hampir seperti catatan tunggal yang dapat diperbarui yang digunakan dalam kueri. Anda tidak perlu menerapkan kondisi "Gabung" tertentu karena mungkin tidak ada kaitannya dengan tabel lainnya dalam kueri... Intinya, membuat hasil Cartesian, tetapi satu catatan terhadap tabel lain tidak akan pernah dibuat duplikat, jadi tidak ada kerusakan di bagian hilir.
select
...
from
( select @SomeVar := 0,
@SomeDate := curdate(),
@SomeString := "hello" ) as SQLVars
Sekarang, bagaimana sqlvars bekerja. Pikirkan program linier... Satu perintah dieksekusi dalam urutan yang tepat saat kueri berjalan. Nilai itu kemudian disimpan kembali di catatan "SQLVars" yang siap untuk waktu berikutnya. Namun, Anda tidak mereferensikannya sebagai SQLVars.SomeVar atau SQLVars.SomeDate... hanya @SomeVar :=someNewValue. Sekarang, ketika @var digunakan dalam kueri, itu juga disimpan sebagai "Sebagai Nama Kolom" di kumpulan hasil. Kadang-kadang, ini bisa menjadi nilai yang dihitung sebagai placeholder dalam persiapan rekaman berikutnya. Setiap nilai kemudian langsung tersedia untuk baris berikutnya. Jadi, berikan contoh berikut...
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
Perhatikan bagaimana nilai @SomeVar digunakan saat setiap kolom menggunakannya... Jadi bahkan pada catatan yang sama, nilai yang diperbarui segera tersedia untuk kolom berikutnya... Yang mengatakan, sekarang lihat mencoba membuat jumlah catatan yang disimulasikan / peringkat per setiap pelanggan...
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
Klausa "Order By" memaksa hasil dikembalikan secara berurutan terlebih dahulu. Jadi, di sini, catatan per pelanggan dikembalikan. Pertama kali melalui, LastID adalah 0 dan ID pelanggan mengatakan...5. Karena berbeda, ia mengembalikan 1 sebagai @SeqNo, MAKA ia mempertahankan ID pelanggan itu ke dalam bidang @LastID untuk catatan berikutnya. Sekarang, catatan berikutnya untuk pelanggan... ID terakhir adalah sama, jadi dibutuhkan @SeqNo (sekarang =1), dan menambahkan 1 ke 1 dan menjadi #2 untuk pelanggan yang sama... Lanjutkan di jalan.. .
Untuk menjadi lebih baik dalam menulis kueri, lihat tag MySQL dan lihat beberapa kontributor berat. Lihatlah pertanyaan dan beberapa jawaban kompleks dan bagaimana pemecahan masalah bekerja. Bukan untuk mengatakan tidak ada orang lain dengan skor reputasi yang lebih rendah yang baru memulai dan benar-benar kompeten, tetapi Anda akan menemukan siapa yang memberikan jawaban yang baik dan mengapa. Lihat juga riwayat jawaban yang diposting. Semakin banyak Anda membaca dan mengikuti, semakin Anda akan lebih menguasai penulisan kueri yang lebih kompleks.