webForumDet fria alternativet

Flera JOIN problematiskt

7 svar · 289 visningar · startad av Marcus E

Marcus EMedlem sedan maj 20021 466 inlägg
#1

Jag har denna fråga:

SELECT Category.*, COUNT(Category2.ID) AS CategoryCount, COUNT(Product.ID) AS ProductCount
				FROM Category
				LEFT JOIN Product ON FIND_IN_SET(Category.ID, Product.CategoryIDs)
				LEFT JOIN Category AS Category2 ON FIND_IN_SET(Category.ID, Category2.CategoryIDs)
				WHERE Category.ParentID=0
				GROUP BY Category.ID;

COUNT-värdena blir för stora när båda JOIN-satserna används samtidigt. Det beror nog på att alla tre tabeller förenas med varandra innan de grupperas. Jag behöver en gruppering innan den andra JOIN-satsen körs. Hur löser man det?

aasahMedlem sedan mars 20034 471 inlägg
#2

Med en temporär tabell. Slå ihop de två tabellerna, gruppera och spara resultatet i en tabell temp. Använd sedan temp till att slå ihop med den tredje. Om jag förstår frågan rätt....

Passa alltså på att räkna i första steget, dvs innan du sparar i temp.

Marcus EMedlem sedan maj 20021 466 inlägg
#3

Ja, jag tänkte just det. Frågan är om det är den smartaste lösningen. Fast det är det nog eftersom jag kan klämma in en WHERE-sats där också som bara påverkar den föreningen.

CREATE TEMPORARY TABLE tmp (
        CategoryID INT(4) UNSIGNED NOT NULL,
        ProductCount  INT(4) UNSIGNED NOT NULL);

INSERT into tmp SELECT Category.ID, COUNT(Product.ID) AS ProductCount
				FROM Category
				INNER JOIN Product ON FIND_IN_SET(Category.ID, Product.CategoryIDs)
				INNER JOIN User ON Product.UserID=User.ID
				WHERE Category.ParentID=0 AND User.ID = 1
				GROUP BY Category.ID;

SELECT Category.*, COUNT(Category2.ID) AS CategoryCount, tmp.ProductCount
				FROM Category
				LEFT JOIN Category AS Category2 ON FIND_IN_SET(Category.ID, Category2.CategoryIDs)
				LEFT JOIN tmp ON Category.ID=tmp.CategoryID

				WHERE Category.ParentID=0
				GROUP BY Category.ID;
DROP TABLE tmp;

Nu är frågan. Drar detta mycket prestanda? Den temporära tabellen skrivs ju inte till sekundärminnet så det lär inte ta alltför lång tid.

OveRRidEMedlem sedan feb. 200112 078 inlägg
#4

Jag kan inte tänka mig att temporärminnestabeller tar så lång tid att hantera.

Är det MSSQL? Varför inte mäta dem med Query Analyzern? Då ser du ju direkt vad det är som tar tid, hur lång tid det tar, hur stor del av fråga som respektive exekvering kostar osv osv.

Marcus EMedlem sedan maj 20021 466 inlägg
#5

MySQL är det. MS SQL byter jag till när jag har råd. :)

OveRRidEMedlem sedan feb. 200112 078 inlägg
#6

Aj då, jag lider med dig. ;)

Hur ofta kommer frågan köras då? Du har ju inga inparametrar enligt vad jag ser, så den borde ju kunna cachas ganska hårt om nu MySQL har stöd för cache av exekveringsplaner.

Marcus EMedlem sedan maj 20021 466 inlägg
#7

Den kommer att köras varje gång man vill visa kategorier. Det kommer man att vilja göra ofta.

Det finns två inparametrar. De är efter WHERE-satserna.
WHERE Category.ParentID=@CategoryID AND User.ID = @UserID

Marcus EMedlem sedan maj 20021 466 inlägg
#8

Jag provade att byta ut alla JOIN x ON mot JOIN x USING. Det gick inte, varför?

SELECT ...
INNER JOIN User USING(UserID)"
LEFT JOIN Bid USING(BidID)

SELECT ...
INNER JOIN User USING(UserID)"
LEFT JOIN Bid ON Bid.BidID = Product.BidID"

I manualen står det att dessa ska vara exakt lika. Trots det get den första. "Unknown User.BidID' in 'on clause'"

131 ms totalt · 3 externa anrop · v20260731065814-full.30151723
0 ms — hämta forumlista (cache)
0 ms — hämta statistik (cache)
128 ms — hämta tråd, inlägg och bilagor (db)