Avatar billede mishrah Nybegynder
04. september 2013 - 23:27 Der er 9 kommentarer og
1 løsning

SQL unike poster fra tabel1, hvis relationer findes i tabel2

Hej gutter,

Jeg har to tabeller:

Poster:
id
overskrift
tekst

Billeder:
id
post_id
sti
filnavn
prioritet

Jeg har brug for et resultset hvor jeg får top 3 Poster (sorteret efter id DESC) som har billeder tilknyttet (og her skal jeg bruge det først billede, sorteret efter prioritet i billedetabellen):

Dvs. der skal være følgende i resultsettet:
id,overskrift,tekst,sti,filnavn

På forhånd tusind tak,
Med venlig hilsen
Martin
05. september 2013 - 07:30 #1
Det afhænger af hvilket SQL system du bruger.  Med mysql bliver det:

SELECT p.id, overskrift, tekst, sti, filnavn
FROM Poster p
JOIN Billeder b ON p.id = b.post_id
ORDER BY p.id DESC
LIMIT 3

Med MSSQL er det

SELECT TOP 3 p.id, overskrift, tekst, sti, filnavn
FROM Poster p
JOIN Billeder b ON p.id = b.post_id
ORDER BY p.id DESC
Avatar billede mishrah Nybegynder
05. september 2013 - 08:42 #2
Tak for svaret Christian_Belgien :)
Desværre er det ikke løsningen, da en alm. JOIN i mange tilfælde vil give mig flere poster med samme id, overskrift osv.
Det sker fordi der kan være flere billeder tilknyttet samme post og det er netop den problemstilling jeg ikke kan løse.

Jeg skal groft sagt bruge poster med distinct id og som har mindst 1 billede tilknyttet.

Jeg har stadig ikke løst den, selvom jeg har prøvet forskellige joins og select-i-selects. Jeg mistænker man skal have gang i noget groupby men jeg kan ikke få mit hoved i gear til det.. :/
05. september 2013 - 09:11 #3
Ok.  Men så: hvis post med id = 5 har 12 billeder tilknyttet, så vil du kun have id = 5 vist en gang.  Men for hvilket af de 12 billeder vil du så have sti og filnavn?  (Og du fortæller stadig ikke hvilket SQL system du bruger.)
05. september 2013 - 09:18 #4
Hvis du bare vil have sti og filnavn for det første billed i tabelen der er tilknyttet den pågældende post (og hvis du bruger mysql) så skulle dette virke:

SELECT p.id, overskrift, tekst, sti, filnavn
FROM Poster p
JOIN Billeder b ON p.id = b.post_id
GROUP BY p.id
ORDER BY p.id DESC
LIMIT 3
Avatar billede mishrah Nybegynder
05. september 2013 - 10:36 #5
Tak for dit forslag! :)
Den giver dog: Column 'Poster.overskrift' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause

Det er i øvrigt MSSQL :)

Og jeg skal som skrevet bare bruge sti+filnavn på det første billede sorteret efter kolonnen prioritet i billedtabellen.

Jeg har egentlig fået den løst på en anden måde nu, men det virker ikke helt fint i kanten :)

Løsning:

with list as (
    SELECT n.id, n.overskrift, n.dato, (SELECT TOP 1 (sti+filnavn) AS filsti FROM Billeder WHERE post_id = n.id AND sti is not NULL ORDER by prioritet ASC) AS filsti FROM Poster n
)
select * from list where list.filsti is not null ORDER by dato DESC

Tror dog det kan laves bedre med noget GroupBy?
Avatar billede Broholm Novice
05. september 2013 - 14:40 #6
Hvad med denne her:

SELECT TOP 3 P.id, P.overskrift, P.tekst, B.sti, B.filnavn
FROM Billeder AS B
INNER JOIN (
    SELECT Billeder.post_id,Prioritet = MIN(Billeder.prioritet)
    FROM Billeder
    GROUP BY Billeder.post_id
) AS F ON (F.post_id = B.post_id AND F.Prioritet = B.prioritet)
INNER JOIN Poster AS P ON (P.id = B.post_id)
ORDER BY P.id DESC

Jeg ved ikke hvordan din Billeder.Prioritet "vender", men det er bare at bruge MAX() i stedet for MIN()

/Broholm
05. september 2013 - 14:56 #7
Ja, den var snild, broholm.
Avatar billede Broholm Novice
05. september 2013 - 15:15 #8
Måske du skal lægge TOP 3 ind i en inderste SELECT for at få en bedre plan ved store mængder data, men jeg har ikke lige data til at på- eller afvise det:

SELECT P.id, P.overskrift, P.tekst, B.sti, B.filnavn
FROM Billeder AS B
INNER JOIN (
    SELECT TOP 3 Billeder.post_id,Prioritet = MIN(Billeder.prioritet)
    FROM Billeder
    GROUP BY Billeder.post_id
    ORDER BY post_id
) AS F ON (F.post_id = B.post_id AND F.Prioritet = B.prioritet)
INNER JOIN Poster AS P ON (P.id = B.post_id)
ORDER BY P.id DESC
Avatar billede mishrah Nybegynder
05. september 2013 - 15:39 #9
Tak broholm og Christian_belgien for Jeres gode svar :)
Det løste i hvert fald opgaven, men det viser sig at følgende er hurtigst execution:

with list as (
    SELECT TOP 3 n.id, n.overskrift, n.dato, (SELECT TOP 1 (sti+filnavn) AS filsti FROM Billeder WHERE post_id = n.id AND sti is not NULL ORDER by prioritet ASC) AS filsti FROM Poster n
)
select * from list where list.filsti is not null ORDER by dato DESC

Endnu engang tak for hjælpen!
Håber det kan hjælpe andre også.

/Martin
Avatar billede Broholm Novice
05. september 2013 - 15:55 #10
Jeg får ikke samme resultat på din forespørgsel, så det er svært at sammenligne dem. Spørgsmålet er hvilken der er korrekt? :-)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester