Oracle query min() met description

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • smeerbartje
  • Registratie: September 2006
  • Laatst online: 11-09 18:50
Ik heb volgens mij een redelijk veelvoorkomend probleem. Ik wil namelijk de description en een min() functie uitvoeren op 1 tabel.

code:
1
2
3
4
select desc, min(rate)
  from test
 where id ='1234'
 group by desc


Ik verwacht nu als output iets van:
code:
1
2
DESC     MIN(RATE)
desc1      4

Maar ik krijg een ORA-00937: not a single-group group function fout. Echter ik heb al geprobeerd om eeen group-by toe te voegen, maar dan krijg ik ALLES uit 'test' terug. In welke richting moet ik het zoeken?

Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Als dit de exacte query is zoals je 'm uitvoert dan moet de group by in ieder geval goed zijn (of is desc een blob/text/memo i.t.t. een varchar ofzo misschien?)

Als je echter ("voor het gemak") één of een paar velden achterwege hebt gelaten dan is de melding logisch en helder. Zie in dat geval ook Hoe werkt dat GROUP BY nu eigenlijk?

[edit]
:F 8)7 Goeiemorgen :X Je beseft dat desc een reserved keyword is? ;) Effe escapen dus.

[ Voor 60% gewijzigd door RobIII op 30-11-2010 16:55 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • smeerbartje
  • Registratie: September 2006
  • Laatst online: 11-09 18:50
Mijn tabel ziet eruit als:

code:
1
2
3
4
5
6
NAAM     RATE
-----    -----
naam1    1
naam2    2
naam3    3
naam4    4


En nu wil ik met een query de NAAM van het record met de laagste rate vinden. Misschien handig te vermelden dat ik Oracle gebruik.

[ Voor 22% gewijzigd door smeerbartje op 30-11-2010 16:56 ]


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Zie mijn edit ;)
smeerbartje schreef op dinsdag 30 november 2010 @ 16:51:
Misschien handig te vermelden dat ik Oracle gebruik.
Staat toch al in je topictitel? ;) En anders geeft de foutmelding 't wel weg :P

[ Voor 6% gewijzigd door RobIII op 30-11-2010 16:53 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • smeerbartje
  • Registratie: September 2006
  • Laatst online: 11-09 18:50
nee sorry, ik 'verduidelijk' de titels. Je kunt voor "DESC" ook "naam" nemen. Puntje bij paaltje is dat ik de naam terugwil uit dezelfde tabel van het record met de laagste rate. Ik heb je group-by-uitleg gelezen, maar hier word ik niet heel veel wijzer uit.

Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
smeerbartje schreef op dinsdag 30 november 2010 @ 16:55:
nee sorry, ik 'verduidelijk' de titels.
Niet doen. Post de exacte query zoals je 'm naar je DBMS stuurt.
smeerbartje schreef op dinsdag 30 november 2010 @ 16:55:
Ik heb je group-by-uitleg gelezen, maar hier word ik niet heel veel wijzer uit.
Je moet alle velden die niet in een aggregate functie zijn opgenomen in de group by clause zetten. En daarom vermoedde ik al dat je niet de exacte query post(te). En dat is ook precies wat in dat stukje staat waar ik naar verwees.

[ Voor 49% gewijzigd door RobIII op 30-11-2010 16:58 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • smeerbartje
  • Registratie: September 2006
  • Laatst online: 11-09 18:50
Oke, even overnieuw: mijn tabel is:
code:
1
2
3
4
5
6
NAAM     RATE
-----    -----
naam1    1
naam2    2
naam3    3
naam4    4


Nu wil ik met DEZE query de naam van het record met de laagste rate vinden:
code:
1
2
3
select naam, min(rate)
  from test
 group by naam

Acties:
  • 0 Henk 'm!

  • DigiK-oz
  • Registratie: December 2001
  • Laatst online: 16:44
Dat je alle rijen terug krijgt klopt wel, daar vraag je tenslotte om :)

Je zoekt iets als
code:
1
select desc from test where rate=(select min(rate) from test)

Daarnaast is desc geen handige veldnaam, zoals RobIII al vermeldt, dat is vragen om problemen.

[ Voor 3% gewijzigd door DigiK-oz op 30-11-2010 16:59 ]

Whatever


Acties:
  • 0 Henk 'm!

  • smeerbartje
  • Registratie: September 2006
  • Laatst online: 11-09 18:50
RobIII schreef op dinsdag 30 november 2010 @ 16:56:
[...]

Niet doen. Post de exacte query zoals je 'm naar je DBMS stuurt.

[...]

Je moet alle velden die niet in een aggregate functie zijn opgenomen in de group by clause zetten. En daarom vermoedde ik al dat je niet de exacte query post(te). En dat is ook precies wat in dat stukje staat waar ik naar verwees.
Nee, want als ik zowel de naam als de rate 'group-by', dan krijg ik alle waarden terug, terwijl ik aleen maar de min() terug wil.

Acties:
  • 0 Henk 'm!

  • smeerbartje
  • Registratie: September 2006
  • Laatst online: 11-09 18:50
DigiK-oz schreef op dinsdag 30 november 2010 @ 16:58:
Dat je alle rijen terug krijgt klopt wel, daar vraag je tenslotte om :)

Je zoekt iets als
code:
1
select desc from test where rate=(select min(rate) from test)

Daarnaast is desc geen handige veldnaam, zoals RobIII al vermeldt, dat is vragen om problemen.
Maar dit kan niet zonder subquery?

[edit]
Sorry, had een edit moeten doen.... :$

[ Voor 5% gewijzigd door smeerbartje op 30-11-2010 17:00 ]


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
smeerbartje schreef op dinsdag 30 november 2010 @ 16:59:
[...]

Nee, want als ik zowel de naam als de rate 'group-by', dan krijg ik alle waarden terug, terwijl ik aleen maar de min() terug wil.
Als je 't maar voor 1 naam wil dan zul je een where naam = 'foo' moeten toevoegen; je begrijpt de group-by klaarblijkelijk toch nog niet helemaal (en to put it blunt: de basic SQL principes dus ook niet helemaal).

Als je de laagste 'rate' van het hele zooitje wil dan moet je eens kijken naar een having of, makkelijker, een "top 1 met een order" (hoewel oracle volgens mij geen top kent maar wel weer rownum oid; kijk hier eens).

[ Voor 26% gewijzigd door RobIII op 30-11-2010 17:17 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • mphilipp
  • Registratie: Juni 2003
  • Laatst online: 03-09 23:47

mphilipp

Romanes eunt domus

Je krijgt precies wat je vraagt ;)
Als je zegt:
code:
1
2
3
select name, min(sal)
from emp
group by name;


Krijg je de name(s) terug met daarachter het laagste salaris binnen de groepen met dezelfde name. Dus als er 3x een Jan in voorkomt, krijg je maar één Jan terug; die met het laagste salaris. Maar jij wilt wat anders. Jij wilt uit de verzamelijk van Jan, Piet en Karel de persoon met het laagste salaris. In dat geval moet je een voorwaarde aan de group by gaan meegeven mbv having:
code:
1
2
3
4
5
select a.name, min(a.sal)
from emp a
group by a.name
having a.sal=(select min(b.sal)
              from emp b)


Having is zeg maar de where clause van de group by. Met where filter je de rijen die aan de group by meedoen, en met having filter je het resultaat van de group by. De subselect selecteert het laagste salaris uit de tabel en geeft dat aan de hoofdselect terug als voorwaarde voor de having.

De tabelaliassen (a en b) heb ik gedaan voor de duidelijkheid, omdat ik 2x dezelfde tabel gebruik. Ik vind dat een goede gewoonte; zo kan er nooit twijfel bestaan over welke tabel je aan refereert.

Ik doe het wel uit mijn hoofd, maar ik heb de cursus vaak genoeg gegeven dat ik dit onderhand wel moet kunnen.

[edit]
ik doe onhandig zie ik. Having hoeft niet echt persé, alleen als je die groupfunctie in de hoofdselect nodig hebt.

[ Voor 4% gewijzigd door mphilipp op 30-11-2010 17:11 ]

A good way to test the effectiveness and strength of a strategy is to look at whether it contains a strong and authentic tagline.


Acties:
  • 0 Henk 'm!

  • cariolive23
  • Registratie: Januari 2007
  • Laatst online: 18-10-2024
WHERE werkt op record-niveau, HAVING werkt op groeps-niveau.
SQL:
1
2
3
4
5
6
7
8
9
SELECT
  name,
  MIN(sal)
FROM
  emp
WHERE
  name LIKE 'p%'
GROUP BY
  name;

En een voorbeeldje van een HAVING:
SQL:
1
2
3
4
5
6
7
8
9
10
11
SELECT
  name,
  MIN(sal)
FROM
  emp
GROUP BY
  name
HAVING
  MIN(sal) > 100
AND
  COUNT(*) > 2;

Aggregate functies, bv. MIN() of COUNT(), vragen eigenschappen op van een groep records en niet van een individueel record. HAVING gaat controleren of deze groepseigenschap aan een voorwaarde voldoet, bv. dat het minimum sal groter is dan 100 en dat er meer dan 2 records in deze groep zitten. Een combinatie van WHERE en HAVING is ook mogelijk, de WHERE bepaalt of een record in aanmerking komt om in een groep te zitten en de HAVING gaat checken of de groep aan bepaalde voorwaarden voldoet.

Acties:
  • 0 Henk 'm!

  • JB Zimmerman
  • Registratie: April 2000
  • Laatst online: 27-04 01:40
Dit zou je resultaat moeten geven dat je wilt. Namelijk: de naam met de laagste rate.

SQL:
1
2
3
4
5
6
7
8
9
10
11
12
select naam
from (
     select rank() over ( partition by naam order by min_rate desc) rank
          , naam
          , min_rate
     from
     ( select naam, min(rate) min_rate
      from test
      group by naam
    ) min_rate
     )
where rank = 1
Pagina: 1