Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien
Toon posts:

[MySQL] Join rows op ongelijke row-id's

Pagina: 1
Acties:
  • 277 views sinds 30-01-2008
  • Reageer

Verwijderd

Topicstarter
Is het mogelijk om met een bepaalde default waarde te joinen?

Strikt genomen join je 2 kolommen als 2 = 2, 3 = 3, etc. Maar wanneer in de linker tabel 4 wel bestaat, maar in de rechter niet, dat er dan gejoined wordt op bijvoorbeeld 4 = 0 ?

[ Voor 93% gewijzigd door Verwijderd op 17-09-2007 19:06 . Reden: Herziening van een wat onduidelijke vraag... ]


  • KoW
  • Registratie: Juli 2001
  • Laatst online: 17-08-2022

KoW

Parse parsed te veel

zoek eens op outer join

een inner join geeft inderdaad alleen resultaten als de waarde in beide tabellen bestaat. Een outer join geeft ook resultaten die maar in 1 van de tabellen bestaat.

met een beetje geluk heb je in je programmeertaal een functie die de zogenaamde NULL value die je in je reselt set krijgt te defaulten naar iets anders, bv. 0

[ Voor 87% gewijzigd door KoW op 17-09-2007 18:23 ]


Verwijderd

Topicstarter
KoW schreef op maandag 17 september 2007 @ 18:22:
met een beetje geluk heb je in je programmeertaal een functie die de zogenaamde NULL value die je in je reselt set krijgt te defaulten naar iets anders, bv. 0
Ik kom niet verder dan:
code:
1
SELECT * FROM table1 one LEFT JOIN table2 two ON one.id = two.id OR two.id = 0

Ik krijg dan echter de waarden die een 1-op-1 join kunnen maken dubbel terug, omdat ze ook nog eens corresponderen met 0.

Jouw uitleg over teruggekregen NULL waarde defaulten naar 0 begrijp ik niet helemaal. Mijn bedoeling is dus om letterlijk one.id te koppelen aan two.id WHERE two.id = 0... Maar dan alleen als one.id != two.id.

NB: Ik gebruik PHP5+

Verwijderd

SELECT ... FROM tbl1 LEFT JOIN tbl2 ON(tbl1.id = tbl2.id) WHERE tbl2.id IS NULL
Daarmee heb je dus alle rijen uit tbl1 te pakken, en die is gejoint met tbl2, maar als er voor tbl1.id geen gelijke waarde is in tbl2, zijn alle waarden uit tbl2 in het resultaat NULL.

  • mithras
  • Registratie: Maart 2003
  • Niet online
Verwijderd schreef op maandag 17 september 2007 @ 18:35:
[...]

Maar dan alleen als one.id != two.id.
Waarom gebruik je dat statement dan niet :? Je hoeft niet altijd een == relatie te gebruiken, elke comparison kan je in je join statement opnemen, of het =, !=, > of < is, dat maakt niet heel veel uit :)
NB: Ik gebruik PHP5+
Je bent met (my)sql bezig, daar heeft php weinig mee van doen hoor ;)

Verwijderd

Topicstarter
Verwijderd schreef op maandag 17 september 2007 @ 18:40:
SELECT ... FROM tbl1 LEFT JOIN tbl2 ON(tbl1.id = tbl2.id) WHERE tbl2.id IS NULL
Daarmee heb je dus alle rijen uit tbl1 te pakken, en die is gejoint met tbl2, maar als er voor tbl1.id geen gelijke waarde is in tbl2, zijn alle waarden uit tbl2 in het resultaat NULL.
Dit levert me uitsluitend de resultaten op van de rijen waarbij geen join gemaakt kon worden. Ik wil dus de rijen hebben van zowel IS NOT NULL als IS NULL. Waarbij IS NULL gejoined wordt met de tbl2.id = 0...

Als ik doe:

code:
1
SELECT * FROM table1 one LEFT JOIN table2 two ON one.id = two.id OR two.id = 0

Dan krijg ik de rijen die een 1-op-1 join hebben, dubbel terug. Omdat ze dus zowel een join hebben, als ook rij waarbij two.id = 0.

  • KoW
  • Registratie: Juli 2001
  • Laatst online: 17-08-2022

KoW

Parse parsed te veel

Geef eens even wat relevante data dan waarbij het fout gaat.

code:
1
2
3
4
5
6
7
8
one
1
2
3

two
1
2

zou iets moeten geven als
code:
1
2
3
one.1 two.1
one.2 two.2
one.3 NULL

  • Confusion
  • Registratie: April 2001
  • Laatst online: 01-03-2024

Confusion

Fallen from grace

Verwijderd schreef op maandag 17 september 2007 @ 17:43:
Is het mogelijk om met een bepaalde default waarde te joinen?

Strikt genomen join je 2 kolommen als 2 = 2, 3 = 3, etc. Maar wanneer in de linker tabel 4 wel bestaat, maar in de rechter niet, dat er dan gejoined wordt op bijvoorbeeld 4 = 0 ?
Ja, zolang je die default waarden zelf expliciet in de SELECT clause geeft . Dan krijg je iets als
SQL:
1
2
3
4
5
6
SELECT 
    a.id, CASE b.id IS NULL THEN 0 ELSE b.id END 
FROM 
    tableA AS a 
LEFT JOIN 
    tableB AS b ON (a.id = b.id)  

(Afhankelijk van de database die je gebruikt kan de exacte code enigszins varieren.)

Je kan niet elke rij waarvan de ON clause geen matches heeft joinen met een default rij, maar je kan wel die default rij construeren met CASE clauses. Ik denk overigens dat het eleganter is het in de code op te vangen.

[ Voor 20% gewijzigd door Confusion op 17-09-2007 20:19 ]

Wie trösten wir uns, die Mörder aller Mörder?


  • P.O. Box
  • Registratie: Augustus 2005
  • Niet online
ik gok dat je bedoelt dat je, als je waarde niet voorkomt in tabel 2, en dus NULL geeft, dat je dan default de waarde wil hebben bij id 0 uit tabel 2. Dat kun je op meerdere manieren oplossen. Als je toch PHP gebruikt, kun je ook gewoon twee losse queries gebruiken als je er niet uitkomt.
Met MySQL alleen is het ook wel op te lossen. Je kunt in de ON clause van een JOIN meerdere statements gebruiken, en ook is een '='-statement niet verplicht, je kunt daar doen wat je wilt. Je kunt bijvoorbeeld ook nog HAVING tabel2.id = MAX(tabel2.id) gebruiken m.b.v. een group by.

succes :)

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

Er zijn een aantal varianten denkbaar, maar allemaal vrij complex. Sowieso wil je geen left join als ik je goed begrijp maar een gewone inner join op one.id OF op 0, maar die 0 bestaat per definitie wel.

Puur voor de query-complexiteit kan je beter je 0-record los ophalen en die gebruiken in je php-code.

Deze is mogelijk denk ik, maar zal waarschijnlijk niet zo efficient indexen gebruiken:
code:
1
2
3
4
5
6
7
SELECT * FROM table1 one
  JOIN table2 two ON
    CASE WHEN EXISTS
       (SELECT * FROM table2 two_i WHERE two_i.id = one.id)
     THEN one.id = two.id
     ELSE two.id = 0
   END


Of
code:
1
2
3
SELECT * FROM table1 one
  JOIN table2 two ON
      COALESCE((SELECT id FROM table2 two_i WHERE two_i.id = one.id), 0) = two.id


Je kan ook vrij vies de tweede tabel standaard een extra keer meejoinen:
code:
1
2
3
4
SELECT *, COALESCE(two.id, two_bck.id) as id, ...
FROM table1 one
  LEFT JOIN table2 two ON one.id = two.id
  JOIN (SELECT * FROM table2 WHERE id = 0) as two_bck


Of eerst kijken of er wel een id is in tabel 2:
code:
1
2
3
4
5
6
SELECT one.*, two.*
FROM table1 one
  JOIN 
     (SELECT one_t.id, COALESCE(two_t.id, 0) as searchid
          FROM table1 one_t LEFT JOIN table2 two_t USING(id)) as test
  JOIN table2 two ON two.id = test.searchid


En de having-variant van Edwardvb is ook mogelijk. Waarschijnlijk kan je ook nog iets doen met iets als ">= ALL" voor de id's.

[ Voor 4% gewijzigd door ACM op 18-09-2007 10:33 ]

Pagina: 1