Mysql/PHP 1 query laatste datum?

Pagina: 1
Acties:
  • 469 views sinds 30-01-2008

  • ivom
  • Registratie: Januari 2003
  • Laatst online: 17-10 13:52
Hallo,

Weet iemand ook een oplossing om het volgende in 1 query te krijgen, kan helaas
geen query's in querys gebruiken?
Voorbeeld tabel:

omschrijvingbundeldatum
test 1122-12-2004
test 2220-11-2005
test 3111-11-2003
test 4210-10-2003


Als resultaat wil ik graag van elke bundel de rij met de laatste datum hebben.
Met maxdatum in het Select veld, krijg ik alleen de laatste datum.
Daarnaast moeten de rijen vanaf laag naar hoog gesorteerd worden.
Voorbeeld zou dus als resultaat moeten hebben:

test 1122-12-2004
test 2220-11-2005


Zoiets:
Select * from table WHERE table.datum = MAX(table.datum) GROUP by bundel ORDER BY datum
Maar MAX in de WHERE kan dus niet:-).

Iemand een idee, behalve 2 querys :-) ??

Groetjes,

Ivo

  • BasieP
  • Registratie: Oktober 2000
  • Laatst online: 19-10 08:18
kan wel met group by en max, maar ben ff kwijt hoe :P ga ff kijken

SQL:
1
2
3
SELECT MAX(omschrijving) AS omschrijving, bundel, MAX(datum) AS datum
FROM `tabel`
GROUP BY bundel;

[ Voor 255% gewijzigd door BasieP op 11-03-2007 12:26 ]

This message was sent on 100% recyclable electrons.


  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 11:17

Janoz

Moderator Devschuur®

!litemod

@BassieP: Nou, in ieder geval niet op die manier. MAX is een aggregerende functie en niet bedoeld om een specifiek record ergens uit te vissen. De query die je nu geeft levert de grootste datum en de (alfabetisch) grootste omschrijving, maar die hoeven helemaal niet bij hetzelfde record te horen.

@TS: Je zult het met een subquery of met HAVING op moeten lossen.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


  • ivom
  • Registratie: Januari 2003
  • Laatst online: 17-10 13:52
Bedankt voor je reactie.
Gaat helaas zo niet werken.
Het voorbeeld zal wel het goede resultaat geven met MAX(omschrijving) omdat het
toevallig in het voorbeeld goed uit komt :-).
Kwam op internet nog een thread tegen, zelfde probleem:

http://www.byf.nl/viewthr...?tid=2778&page=1#pid24377

Enig idee hoe dat met HAVING is te doen?

[ Voor 6% gewijzigd door ivom op 11-03-2007 12:36 ]


  • pietje63
  • Registratie: Juli 2001
  • Laatst online: 09:37

pietje63

RTFM

Ik zou het oplossen met
- select
- group by `bundel`
- order by datum

maar weet niet 100% zeker of dat klopt.

De grootste Nederlandstalige database met informatie over computers met zoekfunctie!!


  • FragFrog
  • Registratie: September 2001
  • Laatst online: 11:32
pietje63 schreef op zondag 11 maart 2007 @ 15:26:
Ik zou het oplossen met
- select
- group by `bundel`
- order by datum

maar weet niet 100% zeker of dat klopt.
Nee, helaas niet. Probeer het voor de grap maar, hij groepeert eerst en dan worden de groepen op datumvolgorde gezet. Echter, de datum van elke groep is willekeurig (of op primary id meen ik) en dus weet je nooit zeker of je de grootste datum hebt of dat de datum die je hebt wel bij het record wat je wilt hoort - meestal niet.

Hoe het wel kan is zoals gezegd met een subquery of having en ik vermoed zelfs nog wel met distinct, maar dat moet ik even opzoeken :)

//edit
SQL:
1
2
3
4
5
6
7
8
SELECT   name as row_name, omschrijving, datum, id
FROM     tabel_naam
WHERE    id =  (SELECT    id 
                FROM      tabel_naam
                WHERE     name = row_name 
                ORDER BY  datum DESC
                LIMIT     1)
ORDER BY datum DESC

Dit zou volgens mij voor je moeten werken :) Voor elke naam wordt nu het ID van de laatste versie gebruikt om de specifieke rij te selecteren (moet je er natuurlijk wel op letten een unique id te gebruiken als id ;)) en vervolgens wordt het resultaat netjes op datum gesorteert.

Ow, en als je een oude MySQL gebruikt zul je even moeten upgraden, want subqueries werken pas echt lekker vanaf 4.nogwat :+

[ Voor 76% gewijzigd door FragFrog op 11-03-2007 18:18 ]

[ Site ] [ twitch ] [ jijbuis ]


  • XiN-eViL
  • Registratie: Maart 2004
  • Laatst online: 29-08 10:13

XiN-eViL

kzie-nie-veel

SQL:
1
2
3
4
5
6
7
SELECT omschrijving, bundel, datum
FROM `table` as t1
GROUP BY datum
WHERE datum >=
(SELECT datum
FROM `table` as t2
WHERE t2.bundel = table.bundel)

Geen idee of het goed is, heb het niet getest, maar het lijkt me dat zoiets kan :) . Ow en het kan zijn dat je de GROUP BY en de WHERE even moet omwisselen. En je moet ff de order erin fixen :)

[ Voor 17% gewijzigd door XiN-eViL op 11-03-2007 17:38 ]


  • Icelus
  • Registratie: Januari 2004
  • Niet online
Uit het hoofd:
SQL:
1
2
3
4
5
6
    SELECT t1.omschrijving, t1.bundel, t1.datum
      FROM tabel AS t1
INNER JOIN tabel AS t2
        ON t1.bundel = t2.bundel
  GROUP BY t1.bundel, t1.omschrijving, t1.datum
    HAVING t1.datum = MAX(t2.datum)

Developer Accused Of Unreadable Code Refuses To Comment


  • ivom
  • Registratie: Januari 2003
  • Laatst online: 17-10 13:52
Hallo,

Heb het geprobeerd en het werkt inderdaad,
maar ik snap alleen niet helemaal de group by wat hij doet.
GROUP BY t1.bundel, t1.omschrijving, t1.datum

Ik snap dat de bundels gegroepeerd moeten worden, maar waarom
de omschrijving en datum ook?
Als ik dat weg laat krijg ik geen resultaat. Met erbij krijg ik het goede resultaat?

Bedankt.

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Die query groepeert op alle velden van t1, dus levert alleen rijen op welke in de tabel voorkomen en dankzij de having clause wordt de max datum regel afgedwongen. :)

Omdat een waarde van bundel vaker kan voorkomen, leidt een join van de tabel met zichzelf tot meer rijen (carthesisch product is een leuke google term hier ;) ). Bekijk maar wat er gebeurt met
SQL:
1
2
3
4
    SELECT *
      FROM tabel AS t1
INNER JOIN tabel AS t2
        ON t1.bundel = t2.bundel
Als het dan niet duidelijk is, ON clause weglaten en nogmaals resultaat bekijken. ;)

{signature}


  • Icelus
  • Registratie: Januari 2004
  • Niet online
Dit is trouwens ook zonder MAX() te doen:
SQL:
1
2
3
4
5
6
   SELECT t1.*
     FROM tabel AS t1
LEFT JOIN tabel AS t2
       ON t1.bundel = t2.bundel
      AND t1.datum < t2.datum
    WHERE t2.bundel IS NULL
De tabel ‘tabel’ wordt gekoppeld met zichzelf. Bij het koppelen worden alleen de rijen geselecteerd waarbij de kolom ‘bundel’ gelijk is én de datum uit de linker tabel kleiner is dan de datum uit de rechter tabel. Indien de datum gelijk is of groter wordt de waarde NULL ingevuld voor de rechter tabel, dit is dan gelijk de hoogste datum. In de WHERE worden alleen deze rijen (die NULL) zijn uiteindelijk geselecteerd.

Developer Accused Of Unreadable Code Refuses To Comment


  • Bram77
  • Registratie: September 2004
  • Laatst online: 10-07-2023
Ik volg heel even niet hoe ik dit zou moeten toepassen in mijn geval. Da's vast mijn onkunde, maar misschien wil iemand mij toch even assisteren. Ik gebruik de volgende query...

SQL:
1
2
3
4
5
6
7
SELECT * FROM personalia 
INNER JOIN indicatie 
ON (personalia.id = indicatie.idclient) 
WHERE personalia.cluster='clusternaam'
GROUP BY indicatie.idclient 
ORDER BY indicatie.einddatum
DESCENDING


Ik wil dus eigenlijk eerst "ORDER BY" gebruiken en dan pas "GROUP BY", als ik er dan vanuit zou moegen gaan dat hij de eerste entry blijft weergeven heb ik de entry met de datum die ik zoek. helaas werkt het dus niet zo....
Ik heb geprobeert "MIN()" te gebruiken (ik heb de oudste datum nodig, die in de vorm yyyy-mm-dd in de database staat) maar kom er niet uit.

[ Voor 10% gewijzigd door Bram77 op 20-03-2007 15:47 ]


  • Icelus
  • Registratie: Januari 2004
  • Niet online
Bram77 schreef op dinsdag 20 maart 2007 @ 15:43:
Ik volg heel even niet hoe ik dit zou moeten toepassen in mijn geval. Da's vast mijn onkunde, maar misschien wil iemand mij toch even assisteren. Ik gebruik de volgende query...

SQL:
1
2
3
4
5
6
7
SELECT * FROM personalia 
INNER JOIN indicatie 
ON (personalia.id = indicatie.idclient) 
WHERE personalia.cluster='clusternaam'
GROUP BY indicatie.idclient 
ORDER BY indicatie.einddatum
DESCENDING
Ik wil dus eigenlijk eerst "ORDER BY" gebruiken en dan pas "GROUP BY"
Dat is niet mogelijk. ORDER BY wordt altijd na GROUP BY uitgevoerd.
als ik er dan vanuit zou moegen gaan dat hij de eerste entry blijft weergeven heb ik de entry met de datum die ik zoek. helaas werkt het dus niet zo....
Er is geen vaste volgorde van de rijen voordat ORDER wordt uitgevoerd.
Ik heb geprobeert "MIN()" te gebruiken (ik heb de oudste datum nodig, die in de vorm yyyy-mm-dd in de database staat) maar kom er niet uit.
Je zou dit kunnen proberen:
SQL:
1
2
3
4
5
6
7
8
    SELECT p.*
INNER JOIN indicatie AS i2
        ON i1.idclient = i2.idclient
       AND i1.einddatum > i2.einddatum
      FROM personalia AS p, indicatie AS i1
     WHERE p.id = i1.idclient
       AND p.cluster = 'clusternaam'
       AND i2.einddatum IS NULL

Developer Accused Of Unreadable Code Refuses To Comment


  • _eXistenZ_
  • Registratie: Februari 2004
  • Laatst online: 09:38
Je datum moet sowieso als timestamp in de database, dan zou je het kunnen oplossen met een gecorreleerde subquery. Nu heb je gewoon een slechte manier van datums opslaan, wat uitmondt in het niet kunnen queryen van wat jij wil :)

There is no replacement for displacement!


  • Bram77
  • Registratie: September 2004
  • Laatst online: 10-07-2023
Ik weet het. Als ik de applicatie had geschreven die die data in de database zet was dat ook zeker zo geweest.

Bedankt Iclus, ik ga er morgen even mee stoeien.

  • Bram77
  • Registratie: September 2004
  • Laatst online: 10-07-2023
Icelus schreef op dinsdag 20 maart 2007 @ 15:53:
Je zou dit kunnen proberen:
SQL:
1
2
3
4
5
6
7
8
    SELECT p.*
INNER JOIN indicatie AS i2
        ON i1.idclient = i2.idclient
       AND i1.einddatum > i2.einddatum
      FROM personalia AS p, indicatie AS i1
     WHERE p.id = i1.idclient
       AND p.cluster = 'clusternaam'
       AND i2.einddatum IS NULL
Dit volg ik even niet.
AND i1.einddatum > i2.einddatum

Waar haal je die i1 nu vandaan?
Het lijkt er op dat de zelfde waarde wordt vergeleken. Voor de duidelijkheid, de waarde einddatum bestaat maar in één van de tabellen...

  • jan-marten
  • Registratie: September 2000
  • Laatst online: 01-12 15:21
code:
1
SELECT omschrijving, DISTINCT(bundel), datum FROM tabel ORDER BY datum ASC

[ Voor 1% gewijzigd door jan-marten op 21-03-2007 10:25 . Reden: DESC/ASC :o ]


  • Bram77
  • Registratie: September 2004
  • Laatst online: 10-07-2023
Daar had ik ook al even naar gekeken ja, maar wat zou 'bundel' moeten zijn dan?

edit: Ah, ik volg het nu. Maar geeft dit niet het zelfde resultaat als GROUP BY ?

[ Voor 36% gewijzigd door Bram77 op 21-03-2007 10:08 ]


  • jan-marten
  • Registratie: September 2000
  • Laatst online: 01-12 15:21
DISTINCT lijkt idd op GROUP BY.
Er zitten wel wat verschillen tussen: bron...
SELECT DISTINCT(email), newsletter FROM contact_tbl WHERE newsletter != 0;
1721 rows in set (0.42 sec)

SELECT email, newsletter FROM contact_tbl WHERE newsletter != 0 GROUP BY email;
1702 rows in set (0.42 sec)

DISTINCT will in the example above produce more results if a user had been added with more than one type of newsletter. The GROUP BY clause will just get the single email.
NB, grappig om te zien dat wanneer je met Google zoekt naar mysql distinct versus group by je op pagina 2 dit topic al tegenkomt :D

[ Voor 17% gewijzigd door jan-marten op 21-03-2007 10:53 ]


  • Bram77
  • Registratie: September 2004
  • Laatst online: 10-07-2023
Ook met DISTINCT kan ik dus helaas niet wat ik wil.

kan ik hier niet iets mee..
SQL:
1
2
3
...
WHERE indicatie.einddatum=(SELECT MAX(einddatum) FROM indicatie WHERE idclient="idclient in parent query")
...


Dan zou ik dus op de een of andere manier moeten kunnen doorgeven waar de parent query op dat moment is in parsen van de database zodat ik de waarde "idclient" kan meegeven...

[ Voor 11% gewijzigd door Bram77 op 21-03-2007 10:59 ]


  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Jouw vraag is toch echt niet zoveel anders dan wat de TS vroeg. Bekijk die self-join query tot je hem 100% snapt (weet je ook waar bij jouw versie de i1 vandaan moet komen) en pas hem daarna aan voor jouw situatie. Self-join tezamen met MIN of MAX is een veel voorkomend querytype, waar legio voorbeelden van te vinden zijn.

{signature}


  • Bram77
  • Registratie: September 2004
  • Laatst online: 10-07-2023
_eXistenZ_ schreef op dinsdag 20 maart 2007 @ 16:48:
Je datum moet sowieso als timestamp in de database, dan zou je het kunnen oplossen met een gecorreleerde subquery. Nu heb je gewoon een slechte manier van datums opslaan, wat uitmondt in het niet kunnen queryen van wat jij wil :)
Zou je me kunnen vertellen hoe zo'n gecorreleerde subquery toegepast moet worden. Ik heb vanzelfsprekend zelf al vanalles geprobeerd, maar nog zonder succes.

  • Icelus
  • Registratie: Januari 2004
  • Niet online
Moet natuurlijk LEFT JOIN zijn ipv INNER JOIN... :z
SQL:
1
2
3
4
5
6
7
8
   SELECT p.*
LEFT JOIN indicatie AS i2
       ON i1.idclient = i2.idclient
      AND i1.einddatum > i2.einddatum
     FROM personalia AS p, indicatie AS i1
    WHERE p.id = i1.idclient
      AND p.cluster = 'clusternaam'
      AND i2.einddatum IS NULL

Developer Accused Of Unreadable Code Refuses To Comment


  • P.O. Box
  • Registratie: Augustus 2005
  • Niet online
wat een creatieve volgorde van statements.... :?

  • Bram77
  • Registratie: September 2004
  • Laatst online: 10-07-2023
Icelus schreef op donderdag 22 maart 2007 @ 10:00:
Moet natuurlijk LEFT JOIN zijn ipv INNER JOIN... :z
SQL:
1
2
3
4
5
6
7
8
   SELECT p.*
LEFT JOIN indicatie AS i2
       ON i1.idclient = i2.idclient
      AND i1.einddatum > i2.einddatum
     FROM personalia AS p, indicatie AS i1
    WHERE p.id = i1.idclient
      AND p.cluster = 'clusternaam'
      AND i2.einddatum IS NULL
Ik begrijp weer wat meer van hoe je query's complexer kunt maken, bedankt :)

Bovenstaande werkt niet. Misschien kun jij zien wat er mis gaat? Ik post de volledige query zoals hij is.
SQL:
1
2
3
4
5
6
7
8
9
10
11
12
SELECT p.* LEFT JOIN crindicatie 
AS i2 ON i1.idclient=i2.idclient 
AND i1.einddatum>i2.einddatum 
FROM crpersonalia AS p, crindicatie AS i1 
WHERE p.id = i1.idclient 
AND p.cluster!='uitzorg' 
AND p.internelocatieniv1!='uitzorg' 
AND p.internelocatieniv1!='verwijderd' 
AND p.cluster!='' 
AND p.cluster!='NULL' 
AND p.cluster!='test' 
AND i2.einddatum IS NULL

  • P.O. Box
  • Registratie: Augustus 2005
  • Niet online
wat is de foutmelding?

  • Bram77
  • Registratie: September 2004
  • Laatst online: 10-07-2023
code:
1
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'LEFT JOIN crindicatie AS i2 ON i1.idclient=i2.idclient AND i1.einddatum>i2.eindd' at line 1

  • _eXistenZ_
  • Registratie: Februari 2004
  • Laatst online: 09:38
Bram77 schreef op donderdag 22 maart 2007 @ 09:26:
[...]


Zou je me kunnen vertellen hoe zo'n gecorreleerde subquery toegepast moet worden. Ik heb vanzelfsprekend zelf al vanalles geprobeerd, maar nog zonder succes.
Zelf heb ik dit pas op school gehad, maar weet niet meer _precies_ hoe het gaat. Ik ga er even naar kijken :)

There is no replacement for displacement!


  • P.O. Box
  • Registratie: Augustus 2005
  • Niet online
de volgorde van de statements is krom...

probeer:
SQL:
1
2
3
4
5
6
7
8
9
10
select
     selectie
from
     tabelA
left join
     tabelB
on
     koppelingTabelA = koppelingTabelB
where
    voorwaarden

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 11:17

Janoz

Moderator Devschuur®

!litemod

Bram77, PRG is geen afhaalbalie voor kant en klare queries. Wat Icelus post is een ideetje waarmee je verder zou moeten kunnen. Er zit inderdaad een simpele copy past fout in die een syntax error oplevert, maar daarvan verwachten we dat je die makkelijk zelf op zou moeten kunnen lossen.

Ietsje meer zelfredzaamheid zou je niet misstaan.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'

Pagina: 1

Dit topic is gesloten.