webForumDet fria alternativet

Join mot flera tabeller med både INNER och LEFT JOIN.

Databaser & SQL

1 svar · 1 295 visningar · startad av MickeA.com

Medlem sedan feb. 20034 441 inlägg
Frågan#1

Tja,

Har en ganska stor sqlfråga som jag i dagsläget kombinerar med en subfråga för att få ut ett resultat. När "huvudfrågan" loopas igenom körs den andra frågan (också det en join) ett gång per loop.

HUVUDFRÅGA

SELECT
a.field1, 
b.field2, 
c.field3, 
d.field4
FROM tbl1 a 
INNER JOIN tbl2 b
ON a.id = b.parent
  INNER JOIN tbl3 c
  ON b.id = c.parent
    INNER JOIN tbl4 d
    ON c.id = d.parent
WHERE a.field2 = 3
ORDER BY a.field1 ASC;

SUBFRÅGA

SELECT
a.field5,
b.field6
FROM tbl5 a
INNER JOIN tbl6 b
ON a.id = b.parent
WHERE b.foo = <d.field4>
GROUP BY a.field5
ORDER BY a.field5 ASC;

Om den huvudfrågan returnerar mer än 500 rader innebär det att subfrågan kommer att köras 500 ggr. Mitt problem är att det tar alldeles för lång tid att ladda sidan, runt 120 sekunder om det är ~600 rader.

Så, nu vill jag kombinera dessa två...

Eftersom subfrågan idag INTE måste ge några resultat måste jag "knyta" ihop dom här med både INNER och LEFT joins och det här får jag inte till alls.

Har testat med:

SELECT
a.field1, 
b.field2, 
c.field3, 
d.field4,
e.field5,
f.field6
FROM tbl1 a 
INNER JOIN tbl2 b
ON a.id = b.parent
  INNER JOIN tbl3 c
  ON b.id = c.parent
    INNER JOIN tbl4 d
    ON c.id = d.parent
      LEFT JOIN tbl5 e
      ON d.id = e.parent
        LEFT JOIN tbl6 f
	ON e.id = f.parent
WHERE a.field2 = 3
GROUP BY d.id
ORDER BY a.field1 ASC;

Men det blir olika resultat. Subfrågan ska ALDRIG ge mer än 1st träff, den senaste i ordningen om det finns fler.

DBMS är MySQL.

Någon duktig som kan sparka mig i rätt riktning?

Tack!

Medlem sedan mars 20034 471 inlägg
#2

För det första ska man undvika att använda GROUP BY om man inte behöver det för att räkna med aggregerande funktioner PER en partition av värden från de inblandade fälten. Att dömma av hur dina frågor ser ut här, så räknar du ingenting utan tar bara ut olika kolumner rakt av? Om så är fallet kan subfrågan till att börja med skrivas om till:

SUBFRÅGA

SELECT DISTINCT -- <--- Tar bort dubletter
  a.field5,
  b.field6
FROM 
  tbl5 a
  INNER JOIN tbl6 b
     ON a.id = b.parent
WHERE 
  b.foo = <d.field4>
ORDER BY a.field5 ASC;

Dock kommer både din ursprungliga fråga och denna att lämna ifrån sig lika många rader som det finns unika värden på kombinationen (a.field5, b.field6) vilket BÖR vara ett värde per a.field5 eftersom den ursprungliga frågan gick att köra. (Om inte MySQL tillåter GROUP BY-uttryck som andra SQL-databaser inte tillåter, eller "b.field6" i själva verket maskerar en aggregerande funktion på kolumnen.)

För att vara säker på att du bara får ut en rad, kan du ändra uttrycket till:

SELECT DISTINCT -- <--- Tar bort dubletter
  a.field5,
  b.field6
FROM 
  tbl5 a
  INNER JOIN tbl6 b
     ON a.id = b.parent
WHERE 
  b.foo = <d.field4>
ORDER BY a.field5 ASC
LIMIT 1;   -- <--- ta bara med första raden

Det här uttrycket är betydligt skonsammare för DB:n än vad ursprunget är, och tar därför inte alls lika lång tid att köra.

Sedan ger ditt inlägg ingen uppgift om var du stoppar in subfrågan i huvudfrågan idag? Eller gör du det som två separata frågor i en slinga i webbkoden?

För att kunna ge tips om hur du slår ihop det till en fråga måste jag veta hur subfrågans tabeller "sitter ihop med" huvudfrågans. Är några tabeller i de två uttrycken samma? Vilken/vilka kolumner i de respektive tabellerna joinar du på?

I ditt eget förslag på kombination, har du inte heller med någon av de krav du ställer på subfrågan vad jag kan se, vilket gör det än svårare att gissa hur tabellerna sitter ihop.

268 ms totalt · 4 externa anrop · v20260731065814-full.a51de22e
127 ms — deklarationer (db)
0 ms — hämta statistik (cache)
138 ms — hämta tråd, inlägg och bilagor (db)
128 ms — ändringar (db)