[(my)sql] rekenen met subselects?

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • Chrotenise
  • Registratie: December 2011
  • Niet online
Hoi medetweakers,

Op het moment zijn wij bij mijn cursus aangekomen bij het gebruiken van subselects. De opgaven die ik moest doen, moeten dus ook opgelost worden met alleen (sub)selects. Geen joins/unions e.d.

Ik dus overijverig aan het werk en alles is in principe gelukt, behalve deze laatste hersenkraker. Ik heb google afgeplozen uiteraard samen met de handige instructietopic van dit forum, maar heb niet het uiteindelijke antwoord gevonden. Ik hoop nu dat jullie tot mijn redding kunnen komen.

De opgave is als volgt:

'geef het soortnummer(snr) en de nederlandse soortnaam(nsnaam) van die soorten die uitsluitend vis als voedsel hebben.'

Koppeling is als volgt:

snr/snaam zijn columns van soort
snr/voednr zijn columns van dieet
voedsoort/voednr zijn columns van voedsel

Mijn query:

SELECT IFNULL(snr,0) , snaam) FROM soort WHERE snr IN -- om eventule nulwaardes eruit te filteren, ifnull gedaan.
( SELECT snr FROM dieet WHERE voednr IN
( SELECT voednr FROM voedsel WHERE voedselsoort = 'vis' AND snr = -- hierna gaat het dus fout
( SELECT count(snr) = 1 FROM dieet)));

Ik ben tot het volgende gekomen met de volgende logica:

Eindresultaat moet van soort zijn;
Soort moet je koppelen aan dieet om bij voedsel te komen;
In dieet kan je kijken hoeveel verschillende soorten voedsel elke soort eet. Hier dien je dus te filteren naar dat het soort maar 1 soort voedsel eet (vis.)
In voedsel dien je uiteindelijk het resultaat te filteren naar vis.
Omdat dieet eerder komt dan voedsel, heb ik nog een laatste subselect gedaan terug naar dieet omdat je eerst moet filteren naar aantal verschillende soorten voedsel voordat je de 'vis' selectie kan doen, anders klopt de output niet.

Ik moet de count in de laatstse subselect gelijkstellen aan 1, omdat het maar een soort voedsel mag eten. Deze moet vervolgens doorgegeven worden aan de volgende subselect, alleen dat gebeurt niet. Ik krijg namelijk helemaal geen output meer. Als ik die laatste subselect weglaat, dan krijg ik er 7. Moeten er 3 zijn.

[ Voor 4% gewijzigd door Chrotenise op 09-12-2012 00:58 ]


Acties:
  • 0 Henk 'm!

  • MrAngry
  • Registratie: December 2001
  • Laatst online: 05:07
Heb je al geprobeerd om die count in de where clause van je eerste subquery te trekken:
SELECT snr FROM dieet WHERE voednr IN
( SELECT voednr FROM voedsel WHERE voedselsoort = 'vis' ) AND count(snr) = 1

Er is maar één goed systeem en dat is een geluidsysteem - Sef


Acties:
  • 0 Henk 'm!

  • Chrotenise
  • Registratie: December 2011
  • Niet online
MrAngry schreef op zondag 09 december 2012 @ 01:01:
Heb je al geprobeerd om die count in de where clause van je eerste subquery te trekken:
SELECT snr FROM dieet WHERE voednr IN
( SELECT voednr FROM voedsel WHERE voedselsoort = 'vis' ) AND count(snr) = 1
Krijg ik error 1111: invalid use of group function. Daarnaast is snr geen attribuut van voedsel, alleen van dieet.

[ Voor 7% gewijzigd door Chrotenise op 09-12-2012 01:06 ]


Acties:
  • 0 Henk 'm!

  • MrAngry
  • Registratie: December 2001
  • Laatst online: 05:07
Ok, nou er is natuurlijk een andere manier dan count() om te selecteren voor alleen vis (de foutmelding komt doordat je hier having moet gebruiken, maar ik heb hier geen SQL dus weet niet of dat samengaat met je subquery). Die is wel lelijk, maar wellicht is het in dit geval de bedoeling, iets van not in ('vlees', 'planten') etc. Of <>

Er is maar één goed systeem en dat is een geluidsysteem - Sef


Acties:
  • 0 Henk 'm!

  • Chrotenise
  • Registratie: December 2011
  • Niet online
MrAngry schreef op zondag 09 december 2012 @ 01:14:
Ok, nou er is natuurlijk een andere manier dan count() om te selecteren voor alleen vis (de foutmelding komt doordat je hier having moet gebruiken, maar ik heb hier geen SQL dus weet niet of dat samengaat met je subquery). Die is wel lelijk, maar wellicht is het in dit geval de bedoeling, iets van not in ('vlees', 'planten') etc. Of <>
Het probleem is niet zozeer dat ik niet kan filteren op de waardes van voedselsoort om vis eruit te krijgen. Het probleem is dat je die uitkomsten moet koppelen aan snr om te kijken of die diersoort ook nog andere dingen eet. Ik mag namelijk uiteindelijk alleen de diersoorten weergeven die alleen vis eten.

Acties:
  • 0 Henk 'm!

  • Kalief
  • Registratie: Maart 2005
  • Laatst online: 06-07 09:16
voedsoort/voednr zijn columns van voedsel
( SELECT voednr FROM voedsel WHERE voedselsoort = 'vis' AND snr = -- hierna gaat het dus fout

voedsoort = voedselsoort ?

Niemand wordt Kalief in plaats van de Kalief!


Acties:
  • 0 Henk 'm!

  • Chrotenise
  • Registratie: December 2011
  • Niet online
Kalief schreef op zondag 09 december 2012 @ 01:57:
voedsoort/voednr zijn columns van voedsel
( SELECT voednr FROM voedsel WHERE voedselsoort = 'vis' AND snr = -- hierna gaat het dus fout

voedsoort = voedselsoort ?
Ja. :9

Acties:
  • 0 Henk 'm!

  • Rotterdammertje
  • Registratie: Juni 2002
  • Laatst online: 28-03-2023
Chrotenise schreef op zondag 09 december 2012 @ 00:56:
Mijn query:

SELECT IFNULL(snr,0) , snaam) FROM soort WHERE snr IN -- om eventule nulwaardes eruit te filteren, ifnull gedaan.
( SELECT snr FROM dieet WHERE voednr IN
( SELECT voednr FROM voedsel WHERE voedselsoort = 'vis' AND snr = -- hierna gaat het dus fout
( SELECT count(snr) = 1 FROM dieet)));
Ik denk dat je hier al een aardig eind op weg mee bent. Misschien moet je het eens proberen zonder die count, maar moet je kijken naar alle dieren die een dieet hebben waar de voedselsoort bestaat uit vis, EN waarbij de voedselsoort niet bestaat uit iets anders dan vis (hint hint). ;)

main = putStr (q ++ show q); q = "main = putStr (q ++ show q); q = "


Acties:
  • 0 Henk 'm!

  • Chrotenise
  • Registratie: December 2011
  • Niet online
Rotterdammertje schreef op maandag 10 december 2012 @ 09:43:
[...]


Ik denk dat je hier al een aardig eind op weg mee bent. Misschien moet je het eens proberen zonder die count, maar moet je kijken naar alle dieren die een dieet hebben waar de voedselsoort bestaat uit vis, EN waarbij de voedselsoort niet bestaat uit iets anders dan vis (hint hint). ;)
Dat had ik al door, maar mijn vraag is hoe je dat doet. Want dat komt er op neer dat je 'mag niet anders dan niet vis zijn.' Dit heb ik nog nooit hoeven neerzetten en het enige wat ik kon bedenken werkt niet, nl:

AND NOT voedselsoort IS NOT 'vis'
AND voedselsoort NOT LIKE <> 'vis'

En dat leek me ook niet hoe ik het moest neerzetten. Ik heb vervolgens het geprobeerd door twee subselects in dieet op te nemen:

code:
1
2
3
4
5
6
7
8
9
10
SELECT IFNULL(snr,0), nsnaam -- 10 stuck @ de andere voedselsoorten eruit filteren.
FROM soort
WHERE snr IN (  SELECT snr
                FROM dieet
                WHERE voednr IN (   SELECT voednr
                                    FROM voedsel
                                    WHERE voedselsoort = 'vis')
                AND voednr NOT IN (     SELECT voednr 
                                    FROM voedsel
                                    WHERE voedselsoort NOT LIKE '%vis%'));


Dit zorgt voor de oude bekende met 7 output i.p.v. 3 |:(

[ Voor 36% gewijzigd door Chrotenise op 11-12-2012 01:11 ]


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Dat NOT LIKE enzo lijkt me onzin, voedselsoort<>'vis' zou goed genoeg zijn. Het probleem is dat je de niet-constructie te laat begint. Een dieet is nu goed als er een voedselsoort in zit dat goed bevonden is. Afhankelijk van of een soort meer regels in de tabel dieet heeft, moet je de niet-constructie al gelijk beginnen (met meerdere subselects). Dus je zoekt soorten die geen dieet hebben waar foute dingen opstaan, en wel een dieet hebben met vis erin.

Kijk trouwens ook eens naar (NOT) EXISTS, ik vermoed dat de opdracht op het gebruikt daarvan doelt. :p

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • Chrotenise
  • Registratie: December 2011
  • Niet online
pedorus schreef op dinsdag 11 december 2012 @ 01:27:
Dat NOT LIKE enzo lijkt me onzin, voedselsoort<>'vis' zou goed genoeg zijn. Het probleem is dat je de niet-constructie te laat begint. Een dieet is nu goed als er een voedselsoort in zit dat goed bevonden is. Afhankelijk van of een soort meer regels in de tabel dieet heeft, moet je de niet-constructie al gelijk beginnen (met meerdere subselects). Dus je zoekt soorten die geen dieet hebben waar foute dingen opstaan, en wel een dieet hebben met vis erin.

Kijk trouwens ook eens naar (NOT) EXISTS, ik vermoed dat de opdracht op het gebruikt daarvan doelt. :p
<> mag blijkbaar niet in in die combinatie; mysql keurde het niet goed.

Ik heb vanwege wat jij zei inderdaad nu twee subselects aan dieet gehangen (zie vorige post): eentje geeft een lijst terug met welke voednrs toegestaan zijn en eentje welke niet toegestaan is. Probleem is dat hij de laatste lijst niet gebruikt om de eerste lijst te filteren. 8)7

En nee, dit moet echt met alleen subselects icm wheres op te lossen zijn volgens de docent.

Acties:
  • 0 Henk 'm!

  • Chrotenise
  • Registratie: December 2011
  • Niet online
Eureka!

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
SELECT IFNULL(snr,0) nsnaam -- 10 stuck @ de andere voedselsoorten eruit filteren.
FROM soort
WHERE snr IN (  SELECT snr
                FROM dieet
                WHERE snr NOT IN   ( SELECT DISTINCT snr
                                        FROM dieet
                                        WHERE voednr IN (   SELECT voednr
                                                            FROM voedsel
                                                            WHERE voedselsoort <> 'vis' ))
                AND snr IN (    SELECT snr
                                FROM dieet
                                WHERE voednr IN (   SELECT voednr
                                                    FROM voedsel
                                                    WHERE voedselsoort = 'vis' )));

Acties:
  • 0 Henk 'm!

  • Rotterdammertje
  • Registratie: Juni 2002
  • Laatst online: 28-03-2023
Chrotenise schreef op dinsdag 11 december 2012 @ 02:09:
Eureka!

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
SELECT IFNULL(snr,0) nsnaam -- 10 stuck @ de andere voedselsoorten eruit filteren.
FROM soort
WHERE snr IN (  SELECT snr
                FROM dieet
                WHERE snr NOT IN   ( SELECT DISTINCT snr
                                        FROM dieet
                                        WHERE voednr IN (   SELECT voednr
                                                            FROM voedsel
                                                            WHERE voedselsoort <> 'vis' ))
                AND snr IN (    SELECT snr
                                FROM dieet
                                WHERE voednr IN (   SELECT voednr
                                                    FROM voedsel
                                                    WHERE voedselsoort = 'vis' )));
_/-\o_

Het kan trouwens nog iets korter. Je doet nu een query op dieet met daarin weer een query op dieet. Een beetje overvloedig; die eerste "SELECT snr FROM dieet" hoeft volgens mij niet.

[ Voor 12% gewijzigd door Rotterdammertje op 11-12-2012 13:30 ]

main = putStr (q ++ show q); q = "main = putStr (q ++ show q); q = "


Acties:
  • 0 Henk 'm!

  • Chrotenise
  • Registratie: December 2011
  • Niet online
Rotterdammertje schreef op dinsdag 11 december 2012 @ 12:45:
[...]


_/-\o_

Het kan trouwens nog iets korter. Je doet nu een query op dieet met daarin weer een query op dieet. Een beetje overvloedig; die eerste "SELECT snr FROM dieet" hoeft volgens mij niet.
Goed gezien. Bleek ook dat *** MySQL een null waarde liet zien zodat je makkelijker dingen kan toevoegen. Dacht dat mijn SQL query verkeerd was :X. IFNULL() hoefde dus ook niet.

Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Let overigens op dat een NOT IN-constructie andere resultaten oplevert dan een NOT EXISTS-constructie als er wel een NULL in de set zit. Uitleg: http://www.techrepublic.c...ect-in-and-exists/5319615

Overigens is die DISTINCT ook overbodig ;)

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten

Pagina: 1