Asus EN8800GTS, Asus P5E, Intel E8400, 2x500gb Spinpoint (raid0), Zalman HP 600 watt, cnps 9500 led, creative xfi music, 4x1gb hyperX PC2 8500
Verwijderd
Je kan dan dus a.id selecteren waar a.blaat = $eenvariabele en a.id niet in B.A_id en niet in C.A_id zit.
1
2
3
4
| SELECT a.id FROM A a WHERE a.blaat = $eenvariabele AND a.id NOT IN (SELECT B.A_id FROM B) AND a.id NOT IN (SELECT C.A_id FROM C) |
[ Voor 30% gewijzigd door frickY op 10-01-2010 15:56 ]
Ik heb het nu inderdaad met een outer join gedaan en voor het gemak heb ik de query opgesplitst in twee queries.frickY schreef op zondag 10 januari 2010 @ 15:55:
Probeer het eens met een Outer Join (join B & join C) en een Having clause (HAVING B IS NULL AND C IS NULL).
bedankt.
Asus EN8800GTS, Asus P5E, Intel E8400, 2x500gb Spinpoint (raid0), Zalman HP 600 watt, cnps 9500 led, creative xfi music, 4x1gb hyperX PC2 8500
Volgens mij kan het makkelijk in één query:Meijuh schreef op zondag 10 januari 2010 @ 15:34:
...
code:
1 2 3 4 5 A(id, blaat) B(id, A_id) C(id, A_id) Foreign key B(A_id) references A(id) Foreign key C(A_id) references A(id)
Nu wil ik alle id's van tabel A ophalen die niet in B.A_id of C.A_id zitten, maar ik zie even niet hoe.
1
2
3
4
5
| SELECT A.* FROM A LEFT JOIN B ON B.A_id=A.id LEFT JOIN C ON C.A_id=A.id WHERE ISNULL(B.id) AND ISNULL(C.id) |
Koop of verkoop je webshop: ecquisition.com
Verwijderd
@Meijuh: ik ben wel benieuwd hoe je het dan hebt opgelost met twee queries?
Met "AND a.id NOT IN (SELECT ...)" doe je volgens mij wel drie volledige selects en dat wordt vrij traag. Met een join op indices zoals in mijn oplossing is het een stukje sneller, maar functioneel doet het hetzelfde.Verwijderd schreef op zondag 10 januari 2010 @ 18:32:
De oplossing die ik plaatste deed het ook in één query. Waarom zou je hier een JOIN toepassen en dan checken op NULL?
@Meijuh: ik ben wel benieuwd hoe je het dan hebt opgelost met twee queries?
Ik zou ook wel willen weten wat de TS dan doet met 2 losse query's, want is totaal niet nodig (tenzij de werkelijke logica wat ingewikkelder is dan het gegeven voorbeeld).
Koop of verkoop je webshop: ecquisition.com
Zoals de post boven mij. De join is inderdaad veel sneller.Verwijderd schreef op zondag 10 januari 2010 @ 18:32:
De oplossing die ik plaatste deed het ook in één query. Waarom zou je hier een JOIN toepassen en dan checken op NULL?
Ja dat was ook een beetje vaag hoe ik dat deed, het kan ook prima in 1 query, dus dat heb ik ook maar gedaan:)@Meijuh: ik ben wel benieuwd hoe je het dan hebt opgelost met twee queries?
Asus EN8800GTS, Asus P5E, Intel E8400, 2x500gb Spinpoint (raid0), Zalman HP 600 watt, cnps 9500 led, creative xfi music, 4x1gb hyperX PC2 8500
Verwijderd
Heb het even getest (@MySQL), de JOIN was inderdaad iets sneller (0.0004 vs 0.0005 op mijn "willekeurige" dataset met SQL_NO_CACHE hint). Als je de query profiler gebruikt dan is wel redelijk duidelijk te zien dat de JOIN versie minder verschillende taken afhandelt.mocean schreef op zondag 10 januari 2010 @ 18:50:
[...]
Met "AND a.id NOT IN (SELECT ...)" doe je volgens mij wel drie volledige selects en dat wordt vrij traag. Met een join op indices zoals in mijn oplossing is het een stukje sneller, maar functioneel doet het hetzelfde.
Er lijkt zelfs nog een klein performance verschilletje te zitten tussen WHERE ISNULL(B.A_id) en WHERE B.A_id IS NULL.
Al met al lijkt het me heel sterk dat de ene versie "veel sneller" is dan de andere.
En als je een testset maakt van zeg een miljoen per records per tabel? Ik vermoed dat dan de Join wel heel wat sneller zal worden dan de IN (SELECT ...) constructie.Verwijderd schreef op zondag 10 januari 2010 @ 19:45:
[...]
Heb het even getest (@MySQL), de JOIN was inderdaad iets sneller (0.0004 vs 0.0005 op mijn "willekeurige" dataset met SQL_NO_CACHE hint). Als je de query profiler gebruikt dan is wel redelijk duidelijk te zien dat de JOIN versie minder verschillende taken afhandelt.
Er lijkt zelfs nog een klein performance verschilletje te zitten tussen WHERE ISNULL(B.A_id) en WHERE B.A_id IS NULL.
Al met al lijkt het me heel sterk dat de ene versie "veel sneller" is dan de andere.
Koop of verkoop je webshop: ecquisition.com
1
2
3
4
| SELECT a.id FROM a WHERE a.blaat = $eenvariabele AND NOT EXISTS (SELECT * FROM b WHERE a.id = b.A_id) AND NOT EXISTS (SELECT * FROM c WHERE a.id = c.A_id) |
Maar als het query-technisch handig en mogelijk is, zal inderdaad doorgaans de join-variant in MySQL (iets) sneller zijn.
Verwijderd
@mocean: heb het eens geprobeerd met een testset met een miljoen records voor de A tabel en een willekeurig gevulde B en C tabel met 100000 records. Verassend genoeg kwam na 5 tests de gemiddelde executie tijd voor de JOIN-query op 0.0011 en de "NOT IN"-query op 0.0010.
Dat vind ik ook wel verrassend ja, staan de indices dan ook goed? Snap dan niet zo goed waarom die IN query eigenlijk sneller kan zijn. Maar goed, weer wat geleerd!Verwijderd schreef op zondag 10 januari 2010 @ 22:21:
De EXISTS methode is zelfs nog iets netter geloof ik. (Google eens op IN vs EXISTS.)
@mocean: heb het eens geprobeerd met een testset met een miljoen records voor de A tabel en een willekeurig gevulde B en C tabel met 100000 records. Verassend genoeg kwam na 5 tests de gemiddelde executie tijd voor de JOIN-query op 0.0011 en de "NOT IN"-query op 0.0010.
Koop of verkoop je webshop: ecquisition.com
Verwijderd
Dit is de structuur, zo klopt het geloof ik? (De data zal ik jullie besparen.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| CREATE TABLE IF NOT EXISTS `A` ( `id` int(11) NOT NULL AUTO_INCREMENT, `blaat` varchar(255) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1010003 ; CREATE TABLE IF NOT EXISTS `B` ( `id` int(11) NOT NULL AUTO_INCREMENT, `A_id` int(11) NOT NULL, PRIMARY KEY (`id`,`A_id`), KEY `A_id` (`A_id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=100001 ; CREATE TABLE IF NOT EXISTS `C` ( `id` int(11) NOT NULL AUTO_INCREMENT, `A_id` int(11) NOT NULL, PRIMARY KEY (`id`,`A_id`), KEY `A_id` (`A_id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=100001 ; ALTER TABLE `B` ADD CONSTRAINT `B_ibfk_1` FOREIGN KEY (`A_id`) REFERENCES `A` (`id`) ON DELETE CASCADE ON UPDATE CASCADE; ALTER TABLE `C` ADD CONSTRAINT `C_ibfk_1` FOREIGN KEY (`A_id`) REFERENCES `A` (`id`) ON DELETE CASCADE ON UPDATE CASCADE; |
Ik denk niet dat je een primary key wil hebben op (id,A_id), maar gewoon op (id) aangezien je nooit op (id,A_id) zal zoeken, want dan heb je de hele rij al.Verwijderd schreef op maandag 11 januari 2010 @ 12:31:
Ik vond het ook verassend.
Dit is de structuur, zo klopt het geloof ik? (De data zal ik jullie besparen.)
SQL:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 CREATE TABLE IF NOT EXISTS `A` ( `id` int(11) NOT NULL AUTO_INCREMENT, `blaat` varchar(255) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1010003 ; CREATE TABLE IF NOT EXISTS `B` ( `id` int(11) NOT NULL AUTO_INCREMENT, `A_id` int(11) NOT NULL, PRIMARY KEY (`id`,`A_id`), KEY `A_id` (`A_id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=100001 ; CREATE TABLE IF NOT EXISTS `C` ( `id` int(11) NOT NULL AUTO_INCREMENT, `A_id` int(11) NOT NULL, PRIMARY KEY (`id`,`A_id`), KEY `A_id` (`A_id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=100001 ; ALTER TABLE `B` ADD CONSTRAINT `B_ibfk_1` FOREIGN KEY (`A_id`) REFERENCES `A` (`id`) ON DELETE CASCADE ON UPDATE CASCADE; ALTER TABLE `C` ADD CONSTRAINT `C_ibfk_1` FOREIGN KEY (`A_id`) REFERENCES `A` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
Edit: en je autoincrement snap ik ook niet, waarom niet gewoon 1?
Asus EN8800GTS, Asus P5E, Intel E8400, 2x500gb Spinpoint (raid0), Zalman HP 600 watt, cnps 9500 led, creative xfi music, 4x1gb hyperX PC2 8500
Verwijderd
De AUTO_INCREMENT staat al op een waarde omdat de code die je hierboven ziet gewoon de export is van phpmyadmin.
Koop of verkoop je webshop: ecquisition.com
Verwijderd
Edit: vandaag nog getest, de resultaten waren niet veel anders. Het was overall ietsje sneller (~0.0008), maar de twee queries gingen qua gemiddelde executietijd weer gelijk op.
Is dit de query optimizer die hard z'n best heeft gedaan?
[ Voor 62% gewijzigd door Verwijderd op 13-01-2010 00:07 ]