Kom ihåg mig?
Home Menu

Menu


MySQL-förfrågan

Ämnesverktyg Visningsalternativ
Oläst 2004-11-22, 15:54 #1
Starwebs avatar
Starweb Starweb är inte uppkopplad
Flitig postare
 
Reg.datum: Jan 2004
Inlägg: 332
Starweb Starweb är inte uppkopplad
Flitig postare
Starwebs avatar
 
Reg.datum: Jan 2004
Inlägg: 332
Skulle behöva lite experthjälp gällande en mysql-query.

Det är flera tabeller som ska samköras, och hämta ut "rätt" sorts data från de olika tabellerna från en annonssida, och varje annonstyp är uppdelad i varsin databastabell, beroende på vilken typ av data tabellen innehåller.


Tabell "AdvertiseList" innehåller en lista med övergripande data om vad de andra 3 tabellerna innehåller, såsom Datum, Id, MenuId osv.


Förfrågningen såsom den ser ut idag:
SELECT *
FROM AdvertiseList, Advertise8, Advertise9, Advertise11
WHERE ((AdvertiseList.Id <> 0)
AND ((AdvertiseList.MenuId = '8')
OR (AdvertiseList.MenuId = '9')
OR (AdvertiseList.MenuId = '11'))
AND ((AdvertiseList.AdvertiseId = Advertise8.Id)
OR (AdvertiseList.AdvertiseId = Advertise9.Id)
OR (AdvertiseList.AdvertiseId = Advertise11.Id)))
GROUP BY AdvertiseList.Id
ORDER BY AdvertiseList.Date DESC


- Alla de andra 3 tabellerna, dvs. "Advertise8", "Advertise9" och "Advertise11" innehåller tex. fältet "Header" och "Price"
för namnet på annonser respektive priset, men vid förfrågningen ovan verkar den blanda samman vilken Header resp. Price som den ska visa, ibland tar den Header från Advertise8, ibland från Advertise9 osv...

Vad ska jag göra? Borde väl vara någon JOIN, men är tyvärr inte så haj på SQL, så all hjälp uppskattas.

Det hade fungerat om även Header och Price legat i "AdvertiseList" tabellen, då hade man bara gjort förfrågningen mot just den tabellen, men systemet rullar redan idag, och det innebär en hel del strul att ändra om databasstrukturen idag.
Starweb är inte uppkopplad   Svara med citatSvara med citat
Oläst 2004-11-22, 15:59 #2
Anders Anders är inte uppkopplad
Supermoderator
 
Reg.datum: Oct 2003
Inlägg: 833
Anders Anders är inte uppkopplad
Supermoderator
 
Reg.datum: Oct 2003
Inlägg: 833
Du kan skapa alias för tabellerna såhär:
SELECT * FROM tabell1 AS t1, tabell2 AS t2

Kan kanske även vara bättre om du anger de fält (samt i vilken ordning) som ska hämtas ut. Så istället för * skriver du tex:
SELECT id, col1, col2 FROM ...
eller med alias som ovan:
SELECT t1.id, t1.col1, t2.col1, t2.col2 FROM ...

Då kommer du alltid få samma ordning på datan som hämtas ut.

Sen kan du även (för att korta ner frågan lite) ersätta:
AND ((AdvertiseList.MenuId = '8')
OR (AdvertiseList.MenuId = '9')
OR (AdvertiseList.MenuId = '11'))


med detta:
AND (AdvertiseList.MenuId IN (8,9,11))
Anders är inte uppkopplad   Svara med citatSvara med citat
Oläst 2004-11-22, 16:44 #3
eg0master eg0master är inte uppkopplad
Mycket flitig postare
 
Reg.datum: Oct 2004
Inlägg: 898
eg0master eg0master är inte uppkopplad
Mycket flitig postare
 
Reg.datum: Oct 2004
Inlägg: 898
Ja ditt huvudproblem är ju att du inte har koll på vad du joinar ihop. Och bortsett från de andra generella tipsen du fått så vill du inte ha några "OR" om det går att undvika...

Till att börja med behöver du rätt data:
Kod:
SELECT AL.Date, AL. MenuID, A.Header, A.Prize
FROM AdvertiseList AL, Advertise8 A
WHERE AdvertiseList.Id <> 0
AND AdvertiseList.MenuId = '8'
AND AL.AdvertiseId = A.Id
UNION
SELECT AL.Date, AL. MenuID, A.Header, A.Prize
FROM AdvertiseList AL, Advertise9 A
WHERE AdvertiseList.Id <> 0
AND AdvertiseList.MenuId = '9'
AND AL.AdvertiseId = A.Id
UNION
SELECT AL.Date, AL. MenuID, A.Header, A.Prize
FROM AdvertiseList AL, Advertise11 A
WHERE AdvertiseList.Id <> 0
AND AdvertiseList.MenuId = '11'
AND AL.AdvertiseId = A.Id
Sedan gäller det bara att fundera ut ett lämpligt sätt att sortera resultatet du får. Det är lite klurigare med tanke på att en UNION använts...

Outer joins borde fixa det också:
Kod:
SELECT *
FROM AdvertiseList AL
LEFT OUTER JOIN Advertise8 A8 ON AL.AdvertiseID = A8.ID
LEFT OUTER JOIN Advertise9 A9 ON AL.AdvertiseID = A9.ID
LEFT OUTER JOIN Advertise11 A11 ON AL.AdvertiseID = A11.ID
WHERE
AL. MenuId in (8,9,11)
Order by AL.Date
Om jag var du skulle jag nog bita i det sura äpplet. Din DB-design suger rent ut sagt. Antingen gör du ett script som fixar din DB så du kan få rätt data i en enkel fråga eller så hämtar du först ut det du ska ha ur AdvertiseList och gör sedan nya frågor för att hämta det du behöver i "utökningstabellerna".
eg0master är inte uppkopplad   Svara med citatSvara med citat
Oläst 2004-11-22, 17:44 #4
Anders Anders är inte uppkopplad
Supermoderator
 
Reg.datum: Oct 2003
Inlägg: 833
Anders Anders är inte uppkopplad
Supermoderator
 
Reg.datum: Oct 2003
Inlägg: 833
Citat:
Originally posted by eg0master@Nov 22 2004, 17:44
Ja ditt huvudproblem är ju att du inte har koll på vad du joinar ihop. Och bortsett från de andra generella tipsen du fått så vill du inte ha några "OR" om det går att undvika...
Du menar att man inte vill ha OR men UNION och JOIN?

Starweb: Funkar frågan som den ser ut idag? Om enda problemet är att den blandar ihop fälten behöver du ingen join utan kan bara namnge fälten som jag visade. Sen använder du mysql_fetch_array() (den är något snabbare än mysql_fetch_assoc()) för att hämta ut datan på respektive position. Då får du alltid rätt data.
Anders är inte uppkopplad   Svara med citatSvara med citat
Oläst 2004-11-22, 18:15 #5
Starwebs avatar
Starweb Starweb är inte uppkopplad
Flitig postare
 
Reg.datum: Jan 2004
Inlägg: 332
Starweb Starweb är inte uppkopplad
Flitig postare
Starwebs avatar
 
Reg.datum: Jan 2004
Inlägg: 332
Både sätten fungerar. Alltså dels döpa om fälten enligt ditt sätt Anders, samt att göra på eg0master's sätt:
Kod:
SELECT *
FROM AdvertiseList AL
LEFT OUTER JOIN Advertise8 A8 ON AL.AdvertiseID = A8.ID
LEFT OUTER JOIN Advertise9 A9 ON AL.AdvertiseID = A9.ID
LEFT OUTER JOIN Advertise11 A11 ON AL.AdvertiseID = A11.ID
WHERE
AL. MenuId in (8,9,11)
Order by AL.Date
kommer att fungera.

- Tackar för all hjälp, har fått lite bättre insikt nu. Dock har DB-designen fungerat utmärkt på det den gjort tidigare, och anledningen till att tabellerna delades i flera "undertabeller" var pga. att detta ska bidra till mindre "tryck" på databasen då den endast hämtar lite data ur "huvudtabellen" och sedan resten ur rätt "undertabell"... Jag tycker detta borde vara mycket smartare än att ha allt i en stor tabell, speciellt då de olika tabellerna har flera andra olika fält på varje undertabell - förutom Header och Price.


En annan fråga som har med ämnet att göra:
Hur hade ni valt att struktura databastabellerna för bästa möjliga struktur, om ni utgår ifrån min förfrågning samt att det är en annonssida med flera olika typer av annonser?
Om man lagt allt i en och samma tabell så hade man fått en oerhört bred tabell med en uppsjö av poster, vilket borde vara segare att ladda än ett flertal små som man länkar samman... Eller?

Rätta mig gärna, och kom gärna med andra förslag. Är alltid bra inför framtida projekt.
Starweb är inte uppkopplad   Svara med citatSvara med citat
Oläst 2004-11-22, 19:26 #6
Anders Anders är inte uppkopplad
Supermoderator
 
Reg.datum: Oct 2003
Inlägg: 833
Anders Anders är inte uppkopplad
Supermoderator
 
Reg.datum: Oct 2003
Inlägg: 833
Citat:
Originally posted by Starweb@Nov 22 2004, 19:15
Både sätten fungerar.
Jo, jag ifrågasätter inte om det funkar eller inte. Jag funderade bara på vad som är snabbare att göra. Min erfarenhet av JOIN's är att de kan vara oerhört sega. Tycker att en OR borde vara bättre än en JOIN ur prestandasynpunkt, men jag har inte provat så jag vet inte.
Anders är inte uppkopplad   Svara med citatSvara med citat
Oläst 2004-11-23, 09:25 #7
eg0master eg0master är inte uppkopplad
Mycket flitig postare
 
Reg.datum: Oct 2004
Inlägg: 898
eg0master eg0master är inte uppkopplad
Mycket flitig postare
 
Reg.datum: Oct 2004
Inlägg: 898
Ang OR, OUTER JOIN och UNION:
Alla dessa konstruktioner suger. OR är alltid dåligt. Sannolikheten för en tablescan är nära 1. Har faktiskt aldrig testat just det med en outer join (eller "IN" heller för den delen), men även OUTER JOINs är elaka och bör undvikas. Problemet med UNION är lite mindre dels då den kommer gå igenom inte hela tabellen utan bara det temporära resultatet och även denna overhead kan minimeras med "UNION ALL" om man vet att inga dubletter finns (vilket ju är fallet här, så UNION ALL borde det vara).

vad som är mest segt OR eller OUTER JOIN är i sammanhanget egentligen ointressant då resultatet inte är det samma. Det är två helt skilda konstruktioner med olika syften. Den intressanta jämförelsen är "OR vs IN"

Ang hur du borde designat:
Objektorientering är nyckelordet tror jag. Du ska ha en bastabell (AdvertiseList) med ALLA gemensamma fält. Header och Price är ju gemensamma fält och borde inte funnits i resp. undertabeller.
Sedan kan du skapa utökningar av din bastabell med det specialiserade datat.

Då "borde" du ha ett läge där du i varje given fråga inte behöver blanda in mer än bastabellen och en "barntabell". Om du ändå måste det så slutar det med flera frågor eller hemska outer joins. I alla fall om man ska vara flexibel.

Om antalet "extra" kolumner är relativt få (till antal och datatyp) så skulel jag nog fundera på att ha allt i samma tabell och ha generella kolumner för extra datat givet att jag vill välja ut extradata från flera olika typer av "barn"
eg0master är inte uppkopplad   Svara med citatSvara med citat
Oläst 2004-11-23, 14:17 #8
Starwebs avatar
Starweb Starweb är inte uppkopplad
Flitig postare
 
Reg.datum: Jan 2004
Inlägg: 332
Starweb Starweb är inte uppkopplad
Flitig postare
Starwebs avatar
 
Reg.datum: Jan 2004
Inlägg: 332
Citat:
Originally posted by eg0master@Nov 23 2004, 11:25
Ang hur du borde designat:
Objektorientering är nyckelordet tror jag. Du ska ha en bastabell (AdvertiseList) med ALLA gemensamma fält. Header och Price är ju gemensamma fält och borde inte funnits i resp. undertabeller.
Sedan kan du skapa utökningar av din bastabell med det specialiserade datat.

Då "borde" du ha ett läge där du i varje given fråga inte behöver blanda in mer än bastabellen och en "barntabell". Om du ändå måste det så slutar det med flera frågor eller hemska outer joins. I alla fall om man ska vara flexibel.

Om antalet "extra" kolumner är relativt få (till antal och datatyp) så skulel jag nog fundera på att ha allt i samma tabell och ha generella kolumner för extra datat givet att jag vill välja ut extradata från flera olika typer av "barn"
ALLA gemensamma fält ÄR i bastabellen vilken är AdvertiseList, det bara råkar vara så att de 3 "barnen" som jag ska koppla samman just i denna queryn har både Header och Price.

Men ditt förslag hade varit att istället för som nu har jag 1 BAS, och 10 BARN, så skulle du valt att ha 1 BAS, och 1 BARN ?
Eller bara 1 BAS? Jo, jag tänkte först bara ha 1 BAS, men ändrade det sedan till multipla barntabeller för att inte den tabellen skulle dels bli "för bred", och dels bli "överanvänd"...


- Diskutera gärna vidare, detta är både intressant och lärorikt!
Starweb är inte uppkopplad   Svara med citatSvara med citat
Oläst 2004-11-23, 15:41 #9
Anders Anders är inte uppkopplad
Supermoderator
 
Reg.datum: Oct 2003
Inlägg: 833
Anders Anders är inte uppkopplad
Supermoderator
 
Reg.datum: Oct 2003
Inlägg: 833
Citat:
Originally posted by Starweb@Nov 23 2004, 15:17
ALLA gemensamma fält ÄR i bastabellen vilken är AdvertiseList, det bara råkar vara så att de 3 "barnen" som jag ska koppla samman just i denna queryn har både Header och Price.
Huvudregeln är ju "Make the common case fast". Vad är det för frågor som är vanligast på dessa tabeller? Om "the common case" går att lägga i en tabell kan det ju vara bra.

Bas innehåller all gemensam info. Specifik info för barnet ska bara finnas i tabellen för barnet.
Anders är inte uppkopplad   Svara med citatSvara med citat
Oläst 2004-11-23, 17:08 #10
eg0master eg0master är inte uppkopplad
Mycket flitig postare
 
Reg.datum: Oct 2004
Inlägg: 898
eg0master eg0master är inte uppkopplad
Mycket flitig postare
 
Reg.datum: Oct 2004
Inlägg: 898
För att citera mig själv... Objektorientering är nyckelordet...
jag var inte riktigt med på ditt upplägg. Men samma sak gälelr i flera nivåer i så fall...
Om 3 "barn" har gemensamt data så lägg det i en gemensam tabell...

Men även förslaget att "optimera för det vanligaste" gäller...
Sånt här blir sällan riktigt snyggt och slutar med outer joins om man inte väljer ut saker i flera steg.
eg0master är inte uppkopplad   Svara med citatSvara med citat
Svara


Aktiva användare som för närvarande tittar på det här ämnet: 1 (0 medlemmar och 1 gäster)
 

Regler för att posta
Du får inte posta nya ämnen
Du får inte posta svar
Du får inte posta bifogade filer
Du får inte redigera dina inlägg

BB-kod är
Smilies är
[IMG]-kod är
HTML-kod är av

Forumhopp


Alla tider är GMT +2. Klockan är nu 12:49.

Programvara från: vBulletin® Version 3.8.2
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Svensk översättning av: Anders Pettersson
 
Copyright © 2017