Pokusil bych se to ÚPLNĚ zjednodušit tím, že na vaše ostatní tabulky vložím spouštěče a do vaší tabulky User_Fans přidám jen několik sloupců... Jeden pro každý příslušný počet(), který se snažíte získat... z příspěvků, příspěvků, příspěvků, komentářů, Přidat komentář Líbí se mi.
Když je záznam přidán do kterékoli tabulky, stačí aktualizovat tabulku user_fans tak, aby přidala 1 do počtu... bude to prakticky okamžité na základě ID klíče uživatele. Pokud jde o "LIKES"... Podobné, pouze pod podmínkou, že se něco spustí jako "To se mi líbí", přidejte 1.. Pak bude váš dotaz přímou matematikou na jediném záznamu a nebude se spoléhat na ŽÁDNÁ spojení při výpočtu "vážená" celková hodnota. Jak se vaše tabulka bude ještě zvětšovat, budou se také prodlužovat dotazy, protože mají více dat, která je třeba prolít a agregovat. Procházíte KAŽDÝ záznam user_fan, který v podstatě dotazuje každý záznam ze všech ostatních tabulek.
Vše, co bylo řečeno, ponechat tabulky tak, jak je máte, bych restrukturalizoval následovně...
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
LEVÉ PŘIPOJENÍ k předdotazům provede tyto dotazy JEDNOU, pak se celá věc spojí, místo aby byla zasažena jako dílčí dotaz pro každý záznam. Při použití COALESCE(), pokud ve výsledcích tabulky LEFT JOINed žádné takové položky nejsou, nezasáhnete hodnoty NULL, které zkazí výpočty, takže jsem je nastavil na 000000.
OBjasnění VAŠICH OTÁZEK
Jako "AS AliasResult" můžete mít jakýkoli DOTAZ. "As" lze také použít ke zjednodušení dlouhých názvů tabulek pro snazší čitelnost. Aliasy mohou také používat stejnou tabulku, ale jako jiný alias k získání podobného obsahu, ale pro jiný účel.
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 ...
Nyní třetí dotaz výše není praktický a vyžaduje ( úplný dotaz, jehož výsledkem je alias "PQ" představující "PreQuery"). To lze provést, pokud jste chtěli předem omezit určitou sadu dalších komplexních podmínek a chtěli byste menší sadu PŘED provedením dalších spojení k mnoha dalším tabulkám pro všechny konečné výsledky.
Protože „FROM“ NEMUSÍ být skutečnou tabulkou, ale může to být dotaz sám o sobě, na jakémkoli jiném místě použitém v dotazu, musí vědět, jak na tuto sadu výsledků předběžného dotazu odkazovat.
Také při dotazování na pole mohou být také „Jako FinalColumnName“, aby se výsledky zjednodušily tam, kde budou také použity.
selectCONCAT( User.Salutation, User.LastName ) as CourtesyNamefrom ...
selectOrder.NonTaxable+ Order.Taxable+ ( Order.Taxable * Order.SalesTaxRate ) jako OrderTotalWithTaxfrom ...
Název sloupce „Jak“ NENÍ povinný být souhrnem, ale nejčastěji se tak zobrazuje.
Nyní, s ohledem na proměnné MySQL... Pokud jste prováděli uloženou proceduru, mnoho lidí jim předem deklaruje nastavení výchozích hodnot před zbytkem procedury. Můžete je provést in-line v dotazu pouhým nastavením a uvedením výsledku odkazu "Alias". Při provádění těchto proměnných bude select simulovat vždy vracení JEDNOHO ZÁZNAMU hodnot. Je to skoro jako jeden záznam s možností aktualizace použitý v dotazu. Nemusíte aplikovat žádné specifické podmínky "Připojit", protože to nemusí mít žádný vliv na zbytek tabulek v dotazu... V podstatě vytvoří kartézský výsledek, ale jeden záznam proti jakékoli jiné tabulce nikdy nevytvoří stejně duplikuje, takže žádné poškození po proudu.
select
...
from
( select @SomeVar := 0,
@SomeDate := curdate(),
@SomeString := "hello" ) as SQLVars
Nyní, jak fungují sqlvars. Představte si lineární program... Jeden příkaz se provede v přesném pořadí, jak běží dotaz. Tato hodnota je poté znovu uložena zpět do záznamu "SQLVars" připraveného pro další použití. Neodkazujete však na něj jako na SQLVars.SomeVar nebo SQLVars.SomeDate... pouze na @SomeVar :=someNewValue. Nyní, když je @var použit v dotazu, je také uložen jako "Jako název_sloupce" v sadě výsledků. Někdy to může být jen zástupná vypočítaná hodnota při přípravě dalšího záznamu. Každá hodnota je pak přímo dostupná pro další řádek. Takže s ohledem na následující příklad...
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
Všimněte si, jak se používá hodnota @SomeVar, když ji používá každý sloupec... Takže i na stejném záznamu je aktualizovaná hodnota okamžitě k dispozici pro další sloupec... To znamená, nyní se podívejte na pokus o vytvoření simulovaného počtu záznamů / pořadí na každého zákazníka...
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
Klauzule "Objednat podle" vynutí, aby byly výsledky vráceny v pořadí jako první. Zde jsou tedy vráceny záznamy na zákazníka. Poprvé je LastID 0 a ID zákazníka je řekněme...5. Protože se liší, vrátí 1 jako @SeqNo, POTOM zachová toto ID zákazníka do pole @LastID pro další záznam. Nyní další záznam pro zákazníka... Poslední ID je stejné, takže vezme @SeqNo (nyní =1) a přidá 1 k 1 a stane se #2 pro stejného zákazníka... Pokračujte v cestě.. .
Pokud jde o zlepšení v psaní dotazů, podívejte se na značku MySQL a podívejte se na některé z velkých přispěvatelů. Podívejte se na otázky a některé složité odpovědi a na to, jak funguje řešení problémů. Neříkám, že tu nejsou jiní s nižším skóre reputace, kteří teprve začínají a jsou zcela kompetentní, ale zjistíte, kdo dává dobré odpovědi a proč. Podívejte se také na jejich historii zveřejněných odpovědí. Čím více budete číst a sledovat, tím lépe zvládnete psaní složitějších dotazů.