Toon posts:

[MySQL] één row selecteren in een one-to-many relatie

Pagina: 1
Acties:

Verwijderd

Topicstarter
Vereenvoudigde model:

tabel A:
id
[...]

tabel B:
id
AID
date
[...]

rows in B zijn dmv AID gelinkt aan één row in A, 'date' is een veld waarin een utc timestamp staat.
Een row in tabel A kan niet bestaan, zonder dat er minimaal 1 row in tabel B voorkomt met B.AID = A.id.

Ik wil uit tabel A alle rows selecteren waarbij geldt:
B.AID = A.id
B.id is het eerste (en laagste id) wat bij A.id = B.AID hoort (resultaat van SELECT id FROM B WHERE AID = x ORDER BY id ASC LIMIT 1;)
B.date > tijdX AND B.date < tijdY

Voorbeeldinhoud:
A:
1
2
3

B
id AID date
1 1 4
2 1 5
3 1 6
4 1 9
5 2 7
6 3 9
7 3 10

Als resultaat wil ik dan:
id AID date
6 3 9

Iets als SELECT A.id, B.AID, B.date FROM A INNER JOIN B ON (A.id = B.AID) WHERE B.date = 9 ORDER BY A.id DESC, B.ID ASC; lijkt goed, maar dan krijg ik B.id = 4 ook terug en dat wil ik niet, want die hoort niet bij de eerste van A.id = 1 (de eerste is B.id = 1 namelijk).

Ik hoop dat t een beetje te begrijpen is ;)
Kan dit uberhaupt wel met MySQL 4.0.x?

  • Nick_S
  • Registratie: Juni 2003
  • Laatst online: 10-05 16:41

Nick_S

++?????++ Out of Cheese Error

code:
1
2
3
SELECT A.id, MIN(b.ID), b.AID, b.Date
WHERE A.id = b.AID and A.id = x
GROUP BY  b.ID


Zoiets?

'Nae King! Nae quin! Nae Laird! Nae master! We willna' be fooled agin!'


  • Terranca
  • Registratie: April 2000
  • Laatst online: 13-05 22:23
Probeer eens dat 2e puntje wat je hebt te implementeren:
B.id is het eerste (en laagste id) wat bij A.id = B.AID hoort (resultaat van SELECT id FROM B WHERE AID = x ORDER BY id ASC LIMIT 1;)
(Overigens zou dit niet kloppen met je gewenste resultaat, aangezien hij juist B.id=4 zou geven aangezien deze het laagste B.id heeft :) En je kan beter het laagste id selecteren met de query: SELECT MIN(id) FROM B WHERE AID = x )

Verwijderd

Topicstarter
Terranca schreef op vrijdag 21 januari 2005 @ 12:17:

(Overigens zou dit niet kloppen met je gewenste resultaat, aangezien hij juist B.id=4 zou geven aangezien deze het laagste B.id heeft :) En je kan beter het laagste id selecteren met de query: SELECT MIN(id) FROM B WHERE AID = x )
Het laagste B.id voor b.AID = 1 is 1 (met B.date = 4)

De MIN()-oplossing ga ik zo proberen.

Tot nog toe is het probleem dat bij een WHERE date = x dit wordt toegepast voor dat MIN() (of een order by .. limit ..) wordt toegepast, waardoor de MIN() op het verkeerde resultaat wordt uitgevoerd.
Er gebeurt dus zoiets:
SELECT -> FILTER (date = x) -> MIN() of ORDER BY LIMIT, terwijl die laatste twee stappen andersom uitgevoerd zouden moeten worden.

  • Nick_S
  • Registratie: Juni 2003
  • Laatst online: 10-05 16:41

Nick_S

++?????++ Out of Cheese Error

Dat is toch logisch? Als je eerst zou kijken, welke het laagste ID heeft, zonder naar date te kijken, heeft het daarna geen zin meer om naar date te kijken.

'Nae King! Nae quin! Nae Laird! Nae master! We willna' be fooled agin!'


Verwijderd

Topicstarter
Nick_S schreef op vrijdag 21 januari 2005 @ 12:57:
Dat is toch logisch? Als je eerst zou kijken, welke het laagste ID heeft, zonder naar date te kijken, heeft het daarna geen zin meer om naar date te kijken.
Ja, da's waar. Er is alleen een maar, en dat is dat de date geselecteerd wordt door naar een range te kijken, date > x AND date < y. Hierdoor kan het zijn dat er alsnog meerdere rows per b.AID terug komen en het hoeft niet zo te zijn dat de laagste b.ID voor b.AID = A.ID daar tussen zit. In die situatie wil ik geen rows selecteren.

  • Nick_S
  • Registratie: Juni 2003
  • Laatst online: 10-05 16:41

Nick_S

++?????++ Out of Cheese Error

Ok, ik begrijp je, denk ik, wat beter.

code:
1
2
3
SELECT * FROM A, B where B.AID = A.ID
AND b.Data > x AND b.date < x
AND b.ID IN (SELECT MIN(b.ID) FROM B GROUP BY b.ID)


Misschien zoiets?

'Nae King! Nae quin! Nae Laird! Nae master! We willna' be fooled agin!'


Verwijderd

Topicstarter
Nick_S schreef op vrijdag 21 januari 2005 @ 13:37:
Ok, ik begrijp je, denk ik, wat beter.

code:
1
2
3
SELECT * FROM A, B where B.AID = A.ID
AND b.Data > x AND b.date < x
AND b.ID IN (SELECT MIN(b.ID) FROM B GROUP BY b.ID)


Misschien zoiets?
Zoiets doet het prima voor PostgreSQL (en andere RDBMS met ondersteuning voor subqueries), maar in MySQL, waar ik het in wil gebruiken, werkt dat niet.

  • Nick_S
  • Registratie: Juni 2003
  • Laatst online: 10-05 16:41

Nick_S

++?????++ Out of Cheese Error

Een andere oplossing is dan met een temp table gaan werken, waar je alle A.id, MIN(B.id) inleest en daaroverheen je date selecteren.

Of upgraden naar 4.1, aangezien die wel subqueries ondersteunt, maar dat zal wel geen optie zijn.

'Nae King! Nae quin! Nae Laird! Nae master! We willna' be fooled agin!'


Verwijderd

Topicstarter
Nick_S schreef op vrijdag 21 januari 2005 @ 14:18:
Een andere oplossing is dan met een temp table gaan werken, waar je alle A.id, MIN(B.id) inleest en daaroverheen je date selecteren.
Dat heeft ook al door mijn hoofd geschoten. Ik had alleen gehoopt dat het met één query afgehandeld zou kunnen worden. Ik denk dat ik het hiermee maar moet doen, mits het maken van een temp table niet teveel cpu/tijd in beslag neemt. Het gaat gelukkig niet om iets wat vaak uitgevoerd gaat worden (hooguit 1-2x per dag).
Of upgraden naar 4.1, aangezien die wel subqueries ondersteunt, maar dat zal wel geen optie zijn.
't is wel een optie, maar als t even kan, doe ik dat liever niet.
Pagina: 1