Avatar billede _et Praktikant
27. marts 2012 - 08:38 Der er 6 kommentarer og
1 løsning

Select og Join med nyeste record

Jeg har følgende SQL men den virker ikke efter hensigten.

Jeg vil selecte følgende:

SELECT
p.id,
c.name, c.adr, c.no, c.floor, c.postal, c.town, c.region,
p.voiceno, p.faxno, p.datano, p.serialno,
i.simcard, i.imsi, i.emei,
p.fwttype,
i.softwareversion
FROM product p
inner join customer c on c.id = p.id
left join ident i on i.id = p.id

Derudover vil jeg tilføje felterne statusdate og signalquality fra tabellen statusinfo hvor statusinfo.id = p.id
Problemet er: Der er ikke altid en statusinfo række OG ofte er der flere rækker med samme id, hvorifald den nyeste skal vælge udfra et dato felt.

Kan det gøres direkte i SQL?

Mvh
Teddy
27. marts 2012 - 09:47 #1
Stiller du i realiteten to spørgsmål, for det første hvorfor sql forespørgslen ikke virker efter hensigt og for det andet hvordan du får tilføjet nyeste data fra statusinfo?

Med hensyn til det sidste (tilføje nyeste statusinfo data) vil jeg foreslå denne tilføjelse (ikke testet):

LEFT JOIN statusinfo s ON s.id = p.id AND s.dato = (SELECT MAX(dato) FROM statusinfo WHERE id = p.id)

Med hensyn til det første (at få forespørgslen til at virke efter hensigt) hvis det er relevant:  Det kommer selvfølgelig an på hvad hensigten er.  Fra din forespørgsel ser det ud til, at der er en en-til-en relation mellem product og customer.  Hvert produkt har en og kun en customer og hver customer har et og kun et product.  Ligeledes synes du at have en en-til-en relation mellem product og ident.  Hvis det er hensigten, så er det ikke nødvendigt med to forskellige tabeller.  Hvis der for hvert product id kun er et name, en adr, o.s.v. så put det hele i en række i en tabel.  Det gør forespørgsler simplere.

Men er en-til-en relationerne nu virkelig hensigten?  Jeg ville have troet at en customer i tidens løb kunne købe flere products (ellers er det en skidt forretning) og at der for hvert product, for eksempel en Nokia telefon, eksisterede adskillige eksemplarer.  I så fald skulle du bruge, for eksempel, disse tabeller:

product//kun data om en bestemt produkttype
id type model
1  Nokia 1800
2  Samson F2

ident//data om et bestemt eksemplar. ident.product = produc.id
id product voiceno simcard
1  1    065724398  1Asd5
2  1    072513227  27321f

customer//stamoplysninger om en kunde, uanset hvad kunden har købt
id navn adr
1  Hansen Brogade 5
2  Jensen Smøgen 27

køb//køb.customer = customer.id og køb.ident = ident.id
id customer ident
1    2      2
2    2      1

og så bliver din forespørgsel

SELECT p.id, .....
FROM køb k
JOIN ident i ON k.ident = i.id
JOIN product p ON i.product = p.id
JOIN customer c ON k.customer = c.id
LEFT JOIN statusinfo s ON s.id = i.id AND s.dato = (SELECT MAX(dato) FROM statusinfo WHERE id = i.id)
Avatar billede _et Praktikant
27. marts 2012 - 10:25 #2
1) Det var bare dårligt formuleret - Den viste SQL virker efter hensigten...

Ang. opbygningen af DB så har jeg ikke noget med strukturen at gøre.. jeg arbejder blodt vidre på en allerede etableret model.
Din antagelse omkring 1:1 relationerne er korrekt, og det kunne optimeres, men sådan er det nu en gang.

Jeg har prøvet at tilføje dit foreslag, men min phpMyAdmin går helt amok når jeg forsøger at afvikle den.

Kan du se en umiddelbar fejl?

SELECT
p.id,
c.name, c.adr, c.no, c.floor, c.postal, c.town, c.region,
p.voiceno, p.faxno, p.datano, p.serialno,
i.simcard, i.imsi, i.emei,
p.fwttype,
i.softwareversion,
s.statusdate, s.signalquality
FROM product p
inner join customer c on c.id = p.id
left join ident i on i.id = p.id
LEFT JOIN statusinfo s ON s.id = p.id AND s.statusdate = (SELECT MAX(statusdate) FROM statusinfo WHERE productid = p.id)
29. marts 2012 - 08:14 #3
Jeg kom fra det igen.  'phpMyAdmin går helt amok' er ikke nogen særlig akkurat beskrivelse af hvad der sker.  Du må få en eller anden fejlmelding som du passende kunne have gengivet for at hjælpe med at finde ud af hvor det gik galt.

Men jeg spotter i den sidste linje af queryen i #2 at du siger 'WHERE productid = p.id'.  Eftersom du, så vidt jeg kan se, ikke har noget felt 'productid' i tabellen statusinfo, så skal det gå galt.  Prøv i stedet at følge mit forslag i #1:

'...LEFT JOIN statusinfo s ON s.id = p.id AND s.dato = (SELECT MAX(dato) FROM statusinfo WHERE id = p.id)'

Jeg kan se hvad du har gjort.  Efter at have svaret på dit direkte spørgsmål foreslog jeg dig en ændret tabelstruktur og gav dig en query for hvis du ændrede tabelstrukturen som foreslået.
29. marts 2012 - 08:15 #4
..og det ville jeg have oprettet som svar, så du kan afslutte spørgsmålet og give points.
Avatar billede _et Praktikant
29. marts 2012 - 09:37 #5
Hvis "siden kan ikke vises" er bedre end "helt amok" så er der hermed vidregivet en bedre beskrivelse..

Jeg kan ikke få din model til at generere data, men måske fordi der er for mange felter det kan gå galt med.

men en kort syntax afklaring.

select a.id, a.txt, b.tlf, b.fax, c.stat, c.pid
FROM aaaa a
LEFT join bbbb b on a.id = b.id
RIGHT OUTER JOIN cccc c on a.id = c.pid
AND (SELECT MAX(c.stat) FROM cccc)
WHERE a.id = 100

Hvor a.id = 100 skal returnes a.id a.txt b.tlf b.fax og (MAX(c.stat) med c.pid = a.id )
( Den skal returnere rækken uanset om c.pid findes eller ej - hvis c.stat ikke findes må c.stat vel være null)

Er min syntax så korrekt? Jeg kan ikke helt finde ud af hvor jeg skal placere min WHERE a.id = 100
29. marts 2012 - 10:17 #6
Jeg står og skal afsted.  Lige hurtigt, sammenhængen mellem din oprindelige problemstilling og #5 forstår jeg ikke, jeg kan kikke nærmere senere.  Men når du siger at min model ikke kan generere data, så to hurtigt spørgsmål:  (1) koden i dit oprindelige spørgsmål, giver den det forventede resultat (altså uden status info) uden problemer?  (2) hvad er strukturen i tabellen statusinfo, altså hvilke felter er der og hvad er datatypen for hvert felt?  Hvis statusinfo.id = product.id og der kan være flere rækker status for hver id, således at id ikke er unikt, er der et andet felt i statusinfo der er unikt, som nøgle for tabellen?
Avatar billede _et Praktikant
29. marts 2012 - 10:25 #7
Jeg laver lige en ordenlig beskrivelse senere..

Takker
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
Kategori
Computerworld tilbyder specialiserede kurser i database-management

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